drm/tegra: Changes for v5.9-rc1
This set of patches contains a few preparatory patches to enable video capture support from external camera modules. This is a dependency for the V4L2 driver patches that will likely be merged in v5.9 or v5.10. On top of that there are a couple of fixes across the board as well as some improvements. From a feature point of view this also adds support for horizontal reflection and 180° rotation of planes. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAl8RzoMTHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoWSmEACsfflCDLsEZf/TQevygrp3DLRpwYxz M/aCntrNJE2ACS6QYHaOyea2KZAoyWmrRTLdi6G5zk2w90Qpp4IOx/xLlXT8FMuj 10QXzwof9eu0il9OKawxgKpHLrXbXdxOiTtpM7Iuuc+kj2zxOvz5C1ostR0vxE4F JPSXvwj2uRNBypXPfdd05YV9pUulbGAWD3wAYNR28va8gDU8Ia9zvIrhVMeRHfaU H/0iEMBJaezDTxhzsb4YqS/2nHIAKkEe3O003ppxtXnQf2pwHA22S5JghZcmAzhU 07QiuvHcrsQCsW21D1k4T4vqc5BzrkWchILNQD3BH4OMcoLIUBPI6+AYtP8+g9fd tz1q6YG/ILzS7pZk/39gg6bdqounRHTHmSdhVN+i9sYVqw56xhDgTiwiZ2o9HmgX pWlWVaqnfS6dLPxOd2UA/hi3/zirMeazgvPPJn2rEE1FoH0lro5eoqV+AxtxBkWr ofYsaAr0WRuxCBg9UY7eauKygewTBHiZteRvLykdipDdj7RoY6oPr3KZsqWqvYSM +cJHpbu7eGfoqydWETlR3T8bPR1pbrVbzkyf/EdQMsAltdRLtnq9RggX+k9Z1Dh/ jcW0er2/eXr0pJl79kKRfkva2tgozR2Id+xTZ3HzCVvQNZ5Ixti1SMdo4uRu/xGG 8u3h4G3Sz5mWNw== =d3zu -----END PGP SIGNATURE----- Merge tag 'drm/tegra/for-5.9-rc1' of ssh://git.freedesktop.org/git/tegra/linux into drm-next drm/tegra: Changes for v5.9-rc1 This set of patches contains a few preparatory patches to enable video capture support from external camera modules. This is a dependency for the V4L2 driver patches that will likely be merged in v5.9 or v5.10. On top of that there are a couple of fixes across the board as well as some improvements. From a feature point of view this also adds support for horizontal reflection and 180° rotation of planes. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thierry Reding <thierry.reding@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200717162011.1661788-1-thierry.reding@gmail.com
This commit is contained in:
Коммит
395be0f47a
|
@ -368,6 +368,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
|
|||
h_size = window->src.w * bpp;
|
||||
v_size = window->src.h;
|
||||
|
||||
if (window->reflect_x)
|
||||
h_offset += (window->src.w - 1) * bpp;
|
||||
|
||||
if (window->reflect_y)
|
||||
v_offset += window->src.h - 1;
|
||||
|
||||
value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
|
||||
tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);
|
||||
|
||||
|
@ -404,9 +410,6 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
|
|||
tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
|
||||
}
|
||||
|
||||
if (window->bottom_up)
|
||||
v_offset += window->src.h - 1;
|
||||
|
||||
tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);
|
||||
tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);
|
||||
|
||||
|
@ -470,7 +473,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
|
|||
value |= COLOR_EXPAND;
|
||||
}
|
||||
|
||||
if (window->bottom_up)
|
||||
if (window->reflect_x)
|
||||
value |= H_DIRECTION;
|
||||
|
||||
if (window->reflect_y)
|
||||
value |= V_DIRECTION;
|
||||
|
||||
if (tegra_plane_use_horizontal_filtering(plane, window)) {
|
||||
|
@ -601,7 +607,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
|
|||
struct drm_plane_state *state)
|
||||
{
|
||||
struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
|
||||
unsigned int rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y;
|
||||
unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
|
||||
DRM_MODE_REFLECT_X |
|
||||
DRM_MODE_REFLECT_Y;
|
||||
unsigned int rotation = state->rotation;
|
||||
struct tegra_bo_tiling *tiling = &plane_state->tiling;
|
||||
struct tegra_plane *tegra = to_tegra_plane(plane);
|
||||
struct tegra_dc *dc = to_tegra_dc(state->crtc);
|
||||
|
@ -639,12 +648,26 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rotation = drm_rotation_simplify(state->rotation, rotation);
|
||||
/*
|
||||
* Older userspace used custom BO flag in order to specify the Y
|
||||
* reflection, while modern userspace uses the generic DRM rotation
|
||||
* property in order to achieve the same result. The legacy BO flag
|
||||
* duplicates the DRM rotation property when both are set.
|
||||
*/
|
||||
if (tegra_fb_is_bottom_up(state->fb))
|
||||
rotation |= DRM_MODE_REFLECT_Y;
|
||||
|
||||
rotation = drm_rotation_simplify(rotation, supported_rotation);
|
||||
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
plane_state->reflect_x = true;
|
||||
else
|
||||
plane_state->reflect_x = false;
|
||||
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
plane_state->bottom_up = true;
|
||||
plane_state->reflect_y = true;
|
||||
else
|
||||
plane_state->bottom_up = false;
|
||||
plane_state->reflect_y = false;
|
||||
|
||||
/*
|
||||
* Tegra doesn't support different strides for U and V planes so we
|
||||
|
@ -706,7 +729,8 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
|
|||
window.dst.w = drm_rect_width(&plane->state->dst);
|
||||
window.dst.h = drm_rect_height(&plane->state->dst);
|
||||
window.bits_per_pixel = fb->format->cpp[0] * 8;
|
||||
window.bottom_up = tegra_fb_is_bottom_up(fb) || state->bottom_up;
|
||||
window.reflect_x = state->reflect_x;
|
||||
window.reflect_y = state->reflect_y;
|
||||
|
||||
/* copy from state */
|
||||
window.zpos = plane->state->normalized_zpos;
|
||||
|
@ -792,6 +816,8 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
|
|||
err = drm_plane_create_rotation_property(&plane->base,
|
||||
DRM_MODE_ROTATE_0,
|
||||
DRM_MODE_ROTATE_0 |
|
||||
DRM_MODE_ROTATE_180 |
|
||||
DRM_MODE_REFLECT_X |
|
||||
DRM_MODE_REFLECT_Y);
|
||||
if (err < 0)
|
||||
dev_err(dc->dev, "failed to create rotation property: %d\n",
|
||||
|
@ -1080,6 +1106,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
|
|||
err = drm_plane_create_rotation_property(&plane->base,
|
||||
DRM_MODE_ROTATE_0,
|
||||
DRM_MODE_ROTATE_0 |
|
||||
DRM_MODE_ROTATE_180 |
|
||||
DRM_MODE_REFLECT_X |
|
||||
DRM_MODE_REFLECT_Y);
|
||||
if (err < 0)
|
||||
dev_err(dc->dev, "failed to create rotation property: %d\n",
|
||||
|
@ -2555,10 +2583,8 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(dc->regs);
|
||||
|
||||
dc->irq = platform_get_irq(pdev, 0);
|
||||
if (dc->irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to get IRQ\n");
|
||||
if (dc->irq < 0)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
err = tegra_dc_rgb_probe(dc);
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
|
|
|
@ -136,7 +136,8 @@ struct tegra_dc_window {
|
|||
unsigned int stride[2];
|
||||
unsigned long base[3];
|
||||
unsigned int zpos;
|
||||
bool bottom_up;
|
||||
bool reflect_x;
|
||||
bool reflect_y;
|
||||
|
||||
struct tegra_bo_tiling tiling;
|
||||
u32 format;
|
||||
|
|
|
@ -670,6 +670,7 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
|||
static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||
{
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* XXX Is this still needed? The module reset is deasserted right
|
||||
|
@ -693,7 +694,11 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
|||
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
|
||||
|
||||
return tegra_mipi_calibrate(dsi->mipi);
|
||||
err = tegra_mipi_calibrate(dsi->mipi);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return tegra_mipi_wait(dsi->mipi);
|
||||
}
|
||||
|
||||
static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
|
||||
|
@ -1618,7 +1623,7 @@ static int tegra_dsi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(dsi->regs))
|
||||
return PTR_ERR(dsi->regs);
|
||||
|
||||
dsi->mipi = tegra_mipi_request(&pdev->dev);
|
||||
dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
|
||||
if (IS_ERR(dsi->mipi))
|
||||
return PTR_ERR(dsi->mipi);
|
||||
|
||||
|
|
|
@ -177,6 +177,7 @@ static const u32 gr2d_addr_regs[] = {
|
|||
GR2D_DSTC_BASE_ADDR,
|
||||
GR2D_SRCA_BASE_ADDR,
|
||||
GR2D_SRCB_BASE_ADDR,
|
||||
GR2D_PATBASE_ADDR,
|
||||
GR2D_SRC_BASE_ADDR_SB,
|
||||
GR2D_DSTA_BASE_ADDR_SB,
|
||||
GR2D_DSTB_BASE_ADDR_SB,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define GR2D_DSTC_BASE_ADDR 0x2d
|
||||
#define GR2D_SRCA_BASE_ADDR 0x31
|
||||
#define GR2D_SRCB_BASE_ADDR 0x32
|
||||
#define GR2D_PATBASE_ADDR 0x47
|
||||
#define GR2D_SRC_BASE_ADDR_SB 0x48
|
||||
#define GR2D_DSTA_BASE_ADDR_SB 0x49
|
||||
#define GR2D_DSTB_BASE_ADDR_SB 0x4a
|
||||
|
|
|
@ -381,10 +381,12 @@ static int gr3d_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (gr3d->clk_secondary) {
|
||||
reset_control_assert(gr3d->rst_secondary);
|
||||
tegra_powergate_power_off(TEGRA_POWERGATE_3D1);
|
||||
clk_disable_unprepare(gr3d->clk_secondary);
|
||||
}
|
||||
|
||||
reset_control_assert(gr3d->rst);
|
||||
tegra_powergate_power_off(TEGRA_POWERGATE_3D);
|
||||
clk_disable_unprepare(gr3d->clk);
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
|
|||
copy->tiling = state->tiling;
|
||||
copy->format = state->format;
|
||||
copy->swap = state->swap;
|
||||
copy->bottom_up = state->bottom_up;
|
||||
copy->reflect_x = state->reflect_x;
|
||||
copy->reflect_y = state->reflect_y;
|
||||
copy->opaque = state->opaque;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
|
|
|
@ -46,7 +46,8 @@ struct tegra_plane_state {
|
|||
u32 format;
|
||||
u32 swap;
|
||||
|
||||
bool bottom_up;
|
||||
bool reflect_x;
|
||||
bool reflect_y;
|
||||
|
||||
/* used for legacy blending support only */
|
||||
struct tegra_plane_legacy_blending_state blending[2];
|
||||
|
|
|
@ -2946,7 +2946,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
|
|||
{
|
||||
int err;
|
||||
|
||||
sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io");
|
||||
sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io-hdmi-dp");
|
||||
if (IS_ERR(sor->avdd_io_supply)) {
|
||||
dev_err(sor->dev, "cannot get AVDD I/O supply: %ld\n",
|
||||
PTR_ERR(sor->avdd_io_supply));
|
||||
|
@ -2960,7 +2960,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
|
|||
return err;
|
||||
}
|
||||
|
||||
sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-pll");
|
||||
sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-hdmi-dp-pll");
|
||||
if (IS_ERR(sor->vdd_pll_supply)) {
|
||||
dev_err(sor->dev, "cannot get VDD PLL supply: %ld\n",
|
||||
PTR_ERR(sor->vdd_pll_supply));
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "debug.h"
|
||||
#include "channel.h"
|
||||
|
||||
static DEFINE_MUTEX(debug_lock);
|
||||
|
||||
unsigned int host1x_debug_trace_cmdbuf;
|
||||
|
||||
static pid_t host1x_debug_force_timeout_pid;
|
||||
|
@ -52,12 +54,14 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)
|
|||
struct output *o = data;
|
||||
|
||||
mutex_lock(&ch->cdma.lock);
|
||||
mutex_lock(&debug_lock);
|
||||
|
||||
if (show_fifo)
|
||||
host1x_hw_show_channel_fifo(m, ch, o);
|
||||
|
||||
host1x_hw_show_channel_cdma(m, ch, o);
|
||||
|
||||
mutex_unlock(&debug_lock);
|
||||
mutex_unlock(&ch->cdma.lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -192,8 +192,14 @@ static void show_gather(struct output *o, phys_addr_t phys_addr,
|
|||
|
||||
static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
|
||||
{
|
||||
struct push_buffer *pb = &cdma->push_buffer;
|
||||
struct host1x_job *job;
|
||||
|
||||
host1x_debug_output(o, "PUSHBUF at %pad, %u words\n",
|
||||
&pb->dma, pb->size / 4);
|
||||
|
||||
show_gather(o, pb->dma, pb->size / 4, cdma, pb->dma, pb->mapped);
|
||||
|
||||
list_for_each_entry(job, &cdma->sync_queue, list) {
|
||||
unsigned int i;
|
||||
|
||||
|
|
|
@ -27,10 +27,13 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
|
|||
u32 num_cmdbufs, u32 num_relocs)
|
||||
{
|
||||
struct host1x_job *job = NULL;
|
||||
unsigned int num_unpins = num_cmdbufs + num_relocs;
|
||||
unsigned int num_unpins = num_relocs;
|
||||
u64 total;
|
||||
void *mem;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
|
||||
num_unpins += num_cmdbufs;
|
||||
|
||||
/* Check that we're not going to overflow */
|
||||
total = sizeof(struct host1x_job) +
|
||||
(u64)num_relocs * sizeof(struct host1x_reloc) +
|
||||
|
@ -102,6 +105,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
{
|
||||
struct host1x_client *client = job->client;
|
||||
struct device *dev = client->dev;
|
||||
struct host1x_job_gather *g;
|
||||
struct iommu_domain *domain;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
@ -183,8 +187,14 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
job->num_unpins++;
|
||||
}
|
||||
|
||||
/*
|
||||
* We will copy gathers BO content later, so there is no need to
|
||||
* hold and pin them.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < job->num_gathers; i++) {
|
||||
struct host1x_job_gather *g = &job->gathers[i];
|
||||
size_t gather_size = 0;
|
||||
struct scatterlist *sg;
|
||||
struct sg_table *sgt;
|
||||
|
@ -194,6 +204,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
dma_addr_t *phys;
|
||||
unsigned int j;
|
||||
|
||||
g = &job->gathers[i];
|
||||
g->bo = host1x_bo_get(g->bo);
|
||||
if (!g->bo) {
|
||||
err = -EINVAL;
|
||||
|
@ -213,10 +224,10 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
sgt = host1x_bo_pin(host->dev, g->bo, phys);
|
||||
if (IS_ERR(sgt)) {
|
||||
err = PTR_ERR(sgt);
|
||||
goto unpin;
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
|
||||
if (host->domain) {
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, j)
|
||||
gather_size += sg->length;
|
||||
gather_size = iova_align(&host->iova, gather_size);
|
||||
|
@ -226,7 +237,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
host->iova_end >> shift, true);
|
||||
if (!alloc) {
|
||||
err = -ENOMEM;
|
||||
goto unpin;
|
||||
goto put;
|
||||
}
|
||||
|
||||
err = iommu_map_sg(host->domain,
|
||||
|
@ -235,7 +246,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
if (err == 0) {
|
||||
__free_iova(&host->iova, alloc);
|
||||
err = -EINVAL;
|
||||
goto unpin;
|
||||
goto put;
|
||||
}
|
||||
|
||||
job->unpins[job->num_unpins].size = gather_size;
|
||||
|
@ -245,7 +256,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
DMA_TO_DEVICE);
|
||||
if (!err) {
|
||||
err = -ENOMEM;
|
||||
goto unpin;
|
||||
goto put;
|
||||
}
|
||||
|
||||
job->unpins[job->num_unpins].dir = DMA_TO_DEVICE;
|
||||
|
@ -263,6 +274,8 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
|
||||
return 0;
|
||||
|
||||
put:
|
||||
host1x_bo_put(g->bo);
|
||||
unpin:
|
||||
host1x_job_unpin(job);
|
||||
return err;
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -206,9 +206,9 @@ static int tegra_mipi_power_down(struct tegra_mipi *mipi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct tegra_mipi_device *tegra_mipi_request(struct device *device)
|
||||
struct tegra_mipi_device *tegra_mipi_request(struct device *device,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct device_node *np = device->of_node;
|
||||
struct tegra_mipi_device *dev;
|
||||
struct of_phandle_args args;
|
||||
int err;
|
||||
|
@ -293,22 +293,29 @@ int tegra_mipi_disable(struct tegra_mipi_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(tegra_mipi_disable);
|
||||
|
||||
static int tegra_mipi_wait(struct tegra_mipi *mipi)
|
||||
int tegra_mipi_wait(struct tegra_mipi_device *device)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(250);
|
||||
struct tegra_mipi *mipi = device->mipi;
|
||||
void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2);
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
while (time_before(jiffies, timeout)) {
|
||||
value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
|
||||
if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
|
||||
(value & MIPI_CAL_STATUS_DONE) != 0)
|
||||
return 0;
|
||||
err = clk_enable(device->mipi->clk);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
usleep_range(10, 50);
|
||||
}
|
||||
mutex_lock(&device->mipi->lock);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
err = readl_relaxed_poll_timeout(status_reg, value,
|
||||
!(value & MIPI_CAL_STATUS_ACTIVE) &&
|
||||
(value & MIPI_CAL_STATUS_DONE), 50,
|
||||
250000);
|
||||
mutex_unlock(&device->mipi->lock);
|
||||
clk_disable(device->mipi->clk);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_mipi_wait);
|
||||
|
||||
int tegra_mipi_calibrate(struct tegra_mipi_device *device)
|
||||
{
|
||||
|
@ -374,12 +381,10 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
|
|||
value |= MIPI_CAL_CTRL_START;
|
||||
tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
|
||||
|
||||
err = tegra_mipi_wait(device->mipi);
|
||||
|
||||
mutex_unlock(&device->mipi->lock);
|
||||
clk_disable(device->mipi->clk);
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_mipi_calibrate);
|
||||
|
||||
|
|
|
@ -328,10 +328,12 @@ int host1x_client_resume(struct host1x_client *client);
|
|||
|
||||
struct tegra_mipi_device;
|
||||
|
||||
struct tegra_mipi_device *tegra_mipi_request(struct device *device);
|
||||
struct tegra_mipi_device *tegra_mipi_request(struct device *device,
|
||||
struct device_node *np);
|
||||
void tegra_mipi_free(struct tegra_mipi_device *device);
|
||||
int tegra_mipi_enable(struct tegra_mipi_device *device);
|
||||
int tegra_mipi_disable(struct tegra_mipi_device *device);
|
||||
int tegra_mipi_calibrate(struct tegra_mipi_device *device);
|
||||
int tegra_mipi_wait(struct tegra_mipi_device *device);
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче