diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm-core.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/imx-ldb.c | 151 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-crtc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/parallel-display.c | 10 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-common.c | 12 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-cpmem.c | 13 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-csi.c | 26 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-ic.c | 40 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-prv.h | 1 |
12 files changed, 197 insertions, 114 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 20be86d89a20..99365087645b 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -886,8 +886,12 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) * Each encoder has at most one connector (since we always steal * it away), so we won't call mode_set hooks twice. */ - if (funcs && funcs->mode_set) + if (funcs && funcs->atomic_mode_set) { + funcs->atomic_mode_set(encoder, new_crtc_state, + connector->state); + } else if (funcs && funcs->mode_set) { funcs->mode_set(encoder, mode, adjusted_mode); + } drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode); } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index fc5040ae5f25..15704873fd61 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -657,6 +657,21 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, } EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); +void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags) +{ + *bus_flags = 0; + if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) + *bus_flags |= DRM_BUS_FLAG_PIXDATA_POSEDGE; + if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + *bus_flags |= DRM_BUS_FLAG_PIXDATA_NEGEDGE; + + if (vm->flags & DISPLAY_FLAGS_DE_LOW) + *bus_flags |= DRM_BUS_FLAG_DE_LOW; + if (vm->flags & DISPLAY_FLAGS_DE_HIGH) + *bus_flags |= DRM_BUS_FLAG_DE_HIGH; +} +EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode); + #ifdef CONFIG_OF /** * of_get_drm_display_mode - get a drm_display_mode from devicetree @@ -672,7 +687,8 @@ EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); * 0 on success, a negative errno code when no of videomode node was found. */ int of_get_drm_display_mode(struct device_node *np, - struct drm_display_mode *dmode, int index) + struct drm_display_mode *dmode, u32 *bus_flags, + int index) { struct videomode vm; int ret; @@ -682,6 +698,8 @@ int of_get_drm_display_mode(struct device_node *np, return ret; drm_display_mode_from_videomode(&vm, dmode); + if (bus_flags) + drm_bus_flags_from_videomode(&vm, bus_flags); pr_debug("%s: got %dx%d display mode from %s\n", of_node_full_name(np), vm.hactive, vm.vactive, np->name); diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 9f7dafce3a4c..6dc0ef4cc677 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -58,12 +58,6 @@ static int legacyfb_depth = 16; module_param(legacyfb_depth, int, 0444); #endif -unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc) -{ - return drm_crtc_index(crtc->crtc); -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_id); - static void imx_drm_driver_lastclose(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; @@ -90,24 +84,6 @@ static int imx_drm_driver_unload(struct drm_device *drm) return 0; } -int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) -{ - return drm_crtc_vblank_get(imx_drm_crtc->crtc); -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); - -void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) -{ - drm_crtc_vblank_put(imx_drm_crtc->crtc); -} -EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); - -void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) -{ - drm_crtc_handle_vblank(imx_drm_crtc->crtc); -} -EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); - static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe) { struct imx_drm_device *imxdrm = drm->dev_private; diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h index 07d33e45f90f..5a91cb16c8fa 100644 --- a/drivers/gpu/drm/imx/imx-drm.h +++ b/drivers/gpu/drm/imx/imx-drm.h @@ -13,8 +13,6 @@ struct drm_plane; struct imx_drm_crtc; struct platform_device; -unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc); - struct imx_crtc_state { struct drm_crtc_state base; u32 bus_format; @@ -44,10 +42,6 @@ int imx_drm_init_drm(struct platform_device *pdev, int preferred_bpp); int imx_drm_exit_drm(void); -int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc); -void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc); -void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc); - void imx_drm_mode_config_init(struct drm_device *drm); struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index b03919ed60ba..4eed3a6addad 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -57,7 +57,11 @@ struct imx_ldb_channel { struct imx_ldb *ldb; struct drm_connector connector; struct drm_encoder encoder; + + /* Defines what is connected to the ldb, only one at a time */ struct drm_panel *panel; + struct drm_bridge *bridge; + struct device_node *child; struct i2c_adapter *ddc; int chno; @@ -66,6 +70,7 @@ struct imx_ldb_channel { struct drm_display_mode mode; int mode_valid; u32 bus_format; + u32 bus_flags; }; static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector *c) @@ -251,11 +256,13 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder) drm_panel_enable(imx_ldb_ch->panel); } -static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) +static void +imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *connector_state) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); + struct drm_display_mode *mode = &crtc_state->adjusted_mode; struct imx_ldb *ldb = imx_ldb_ch->ldb; int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; unsigned long serial_clk; @@ -297,17 +304,11 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, } if (!bus_format) { - struct drm_connector *connector; - - drm_for_each_connector(connector, encoder->dev) { - struct drm_display_info *di = &connector->display_info; + struct drm_connector *connector = connector_state->connector; + struct drm_display_info *di = &connector->display_info; - if (connector->encoder == encoder && - di->num_bus_formats) { - bus_format = di->bus_formats[0]; - break; - } - } + if (di->num_bus_formats) + bus_format = di->bus_formats[0]; } imx_ldb_ch_set_bus_format(imx_ldb_ch, bus_format); } @@ -379,8 +380,13 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder, u32 bus_format = imx_ldb_ch->bus_format; /* Bus format description in DT overrides connector display info. */ - if (!bus_format && di->num_bus_formats) + if (!bus_format && di->num_bus_formats) { bus_format = di->bus_formats[0]; + imx_crtc_state->bus_flags = di->bus_flags; + } else { + bus_format = imx_ldb_ch->bus_format; + imx_crtc_state->bus_flags = imx_ldb_ch->bus_flags; + } switch (bus_format) { case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18; @@ -420,7 +426,7 @@ static const struct drm_encoder_funcs imx_ldb_encoder_funcs = { }; static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { - .mode_set = imx_ldb_encoder_mode_set, + .atomic_mode_set = imx_ldb_encoder_atomic_mode_set, .enable = imx_ldb_encoder_enable, .disable = imx_ldb_encoder_disable, .atomic_check = imx_ldb_encoder_atomic_check, @@ -466,10 +472,30 @@ static int imx_ldb_register(struct drm_device *drm, drm_encoder_init(drm, encoder, &imx_ldb_encoder_funcs, DRM_MODE_ENCODER_LVDS, NULL); - drm_connector_helper_add(&imx_ldb_ch->connector, - &imx_ldb_connector_helper_funcs); - drm_connector_init(drm, &imx_ldb_ch->connector, - &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); + if (imx_ldb_ch->bridge) { + imx_ldb_ch->bridge->encoder = encoder; + + imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge; + ret = drm_bridge_attach(drm, imx_ldb_ch->bridge); + if (ret) { + DRM_ERROR("Failed to initialize bridge with drm\n"); + return ret; + } + } else { + /* + * We want to add the connector whenever there is no bridge + * that brings its own, not only when there is a panel. For + * historical reasons, the ldb driver can also work without + * a panel. + */ + drm_connector_helper_add(&imx_ldb_ch->connector, + &imx_ldb_connector_helper_funcs); + drm_connector_init(drm, &imx_ldb_ch->connector, + &imx_ldb_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, + encoder); + } if (imx_ldb_ch->panel) { ret = drm_panel_attach(imx_ldb_ch->panel, @@ -478,8 +504,6 @@ static int imx_ldb_register(struct drm_device *drm, return ret; } - drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, encoder); - return 0; } @@ -548,6 +572,46 @@ static const struct of_device_id imx_ldb_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids); +static int imx_ldb_panel_ddc(struct device *dev, + struct imx_ldb_channel *channel, struct device_node *child) +{ + struct device_node *ddc_node; + const u8 *edidp; + int ret; + + ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); + if (ddc_node) { + channel->ddc = of_find_i2c_adapter_by_node(ddc_node); + of_node_put(ddc_node); + if (!channel->ddc) { + dev_warn(dev, "failed to get ddc i2c adapter\n"); + return -EPROBE_DEFER; + } + } + + if (!channel->ddc) { + /* if no DDC available, fallback to hardcoded EDID */ + dev_dbg(dev, "no ddc available\n"); + + edidp = of_get_property(child, "edid", + &channel->edid_len); + if (edidp) { + channel->edid = kmemdup(edidp, + channel->edid_len, + GFP_KERNEL); + } else if (!channel->panel) { + /* fallback to display-timings node */ + ret = of_get_drm_display_mode(child, + &channel->mode, + &channel->bus_flags, + OF_USE_NATIVE_MODE); + if (!ret) + channel->mode_valid = 1; + } + } + return 0; +} + static int imx_ldb_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; @@ -555,7 +619,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) const struct of_device_id *of_id = of_match_device(imx_ldb_dt_ids, dev); struct device_node *child; - const u8 *edidp; struct imx_ldb *imx_ldb; int dual; int ret; @@ -605,7 +668,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) for_each_child_of_node(np, child) { struct imx_ldb_channel *channel; - struct device_node *ddc_node; struct device_node *ep; int bus_format; @@ -638,46 +700,25 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) remote = of_graph_get_remote_port_parent(ep); of_node_put(ep); - if (remote) + if (remote) { channel->panel = of_drm_find_panel(remote); - else + channel->bridge = of_drm_find_bridge(remote); + } else return -EPROBE_DEFER; of_node_put(remote); - if (!channel->panel) { - dev_err(dev, "panel not found: %s\n", - remote->full_name); - return -EPROBE_DEFER; - } - } - ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); - if (ddc_node) { - channel->ddc = of_find_i2c_adapter_by_node(ddc_node); - of_node_put(ddc_node); - if (!channel->ddc) { - dev_warn(dev, "failed to get ddc i2c adapter\n"); + if (!channel->panel && !channel->bridge) { + dev_err(dev, "panel/bridge not found: %s\n", + remote->full_name); return -EPROBE_DEFER; } } - if (!channel->ddc) { - /* if no DDC available, fallback to hardcoded EDID */ - dev_dbg(dev, "no ddc available\n"); - - edidp = of_get_property(child, "edid", - &channel->edid_len); - if (edidp) { - channel->edid = kmemdup(edidp, - channel->edid_len, - GFP_KERNEL); - } else if (!channel->panel) { - /* fallback to display-timings node */ - ret = of_get_drm_display_mode(child, - &channel->mode, - OF_USE_NATIVE_MODE); - if (!ret) - channel->mode_valid = 1; - } + /* panel ddc only if there is no bridge */ + if (!channel->bridge) { + ret = imx_ldb_panel_ddc(dev, channel, child); + if (ret) + return ret; } bus_format = of_get_bus_format(dev, child); diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 08e188bc10fc..5950b12a15c8 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -134,7 +134,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id) { struct ipu_crtc *ipu_crtc = dev_id; - imx_drm_handle_vblank(ipu_crtc->imx_crtc); + drm_crtc_handle_vblank(&ipu_crtc->base); return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 1dad297b01fd..74b0ac06fdab 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -33,6 +33,7 @@ struct imx_parallel_display { void *edid; int edid_len; u32 bus_format; + u32 bus_flags; struct drm_display_mode mode; struct drm_panel *panel; struct drm_bridge *bridge; @@ -80,6 +81,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) return -EINVAL; ret = of_get_drm_display_mode(np, &imxpd->mode, + &imxpd->bus_flags, OF_USE_NATIVE_MODE); if (ret) return ret; @@ -125,11 +127,13 @@ static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder, struct drm_display_info *di = &conn_state->connector->display_info; struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); - imx_crtc_state->bus_flags = di->bus_flags; - if (!imxpd->bus_format && di->num_bus_formats) + if (!imxpd->bus_format && di->num_bus_formats) { + imx_crtc_state->bus_flags = di->bus_flags; imx_crtc_state->bus_format = di->bus_formats[0]; - else + } else { + imx_crtc_state->bus_flags = imxpd->bus_flags; imx_crtc_state->bus_format = imxpd->bus_format; + } imx_crtc_state->di_hsync_pin = 2; imx_crtc_state->di_vsync_pin = 3; diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 99dcacf05b99..d230988ddb8f 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -45,6 +45,12 @@ static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset) writel(value, ipu->cm_reg + offset); } +int ipu_get_num(struct ipu_soc *ipu) +{ + return ipu->id; +} +EXPORT_SYMBOL_GPL(ipu_get_num); + void ipu_srm_dp_sync_update(struct ipu_soc *ipu) { u32 val; @@ -1004,14 +1010,14 @@ static struct ipu_platform_reg client_reg[] = { .dma[0] = IPUV3_CHANNEL_CSI0, .dma[1] = -EINVAL, }, - .name = "imx-ipuv3-camera", + .name = "imx-ipuv3-csi", }, { .pdata = { .csi = 1, .dma[0] = IPUV3_CHANNEL_CSI1, .dma[1] = -EINVAL, }, - .name = "imx-ipuv3-camera", + .name = "imx-ipuv3-csi", }, { .pdata = { .di = 0, @@ -1209,6 +1215,7 @@ static int ipu_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(imx_ipu_dt_ids, &pdev->dev); + struct device_node *np = pdev->dev.of_node; struct ipu_soc *ipu; struct resource *res; unsigned long ipu_base; @@ -1237,6 +1244,7 @@ static int ipu_probe(struct platform_device *pdev) ipu->channel[i].ipu = ipu; ipu->devtype = devtype; ipu->ipu_type = devtype->type; + ipu->id = of_alias_get_id(np, "ipu"); spin_lock_init(&ipu->lock); mutex_init(&ipu->channel_lock); diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index 6494a4d28171..fcb7dc86167b 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c @@ -253,6 +253,13 @@ void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf) } EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer); +void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off) +{ + ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8); + ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8); +} +EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset); + void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride) { ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1); @@ -268,6 +275,12 @@ void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id) } EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id); +int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch) +{ + return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1; +} +EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize); + void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize) { ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1); diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index 06631ac61b04..d6e5ded24418 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c @@ -258,12 +258,8 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code) cfg->data_width = IPU_CSI_DATA_WIDTH_8; break; case MEDIA_BUS_FMT_UYVY8_1X16: - cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY; - cfg->mipi_dt = MIPI_DT_YUV422; - cfg->data_width = IPU_CSI_DATA_WIDTH_16; - break; case MEDIA_BUS_FMT_YUYV8_1X16: - cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV; + cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; cfg->mipi_dt = MIPI_DT_YUV422; cfg->data_width = IPU_CSI_DATA_WIDTH_16; break; @@ -365,10 +361,14 @@ int ipu_csi_init_interface(struct ipu_csi *csi, { struct ipu_csi_bus_config cfg; unsigned long flags; - u32 data = 0; + u32 width, height, data = 0; fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt); + /* set default sensor frame width and height */ + width = mbus_fmt->width; + height = mbus_fmt->height; + /* Set the CSI_SENS_CONF register remaining fields */ data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT | cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT | @@ -386,11 +386,6 @@ int ipu_csi_init_interface(struct ipu_csi *csi, ipu_csi_write(csi, data, CSI_SENS_CONF); - /* Setup sensor frame size */ - ipu_csi_write(csi, - (mbus_fmt->width - 1) | ((mbus_fmt->height - 1) << 16), - CSI_SENS_FRM_SIZE); - /* Set CCIR registers */ switch (cfg.clk_mode) { @@ -408,11 +403,12 @@ int ipu_csi_init_interface(struct ipu_csi *csi, * Field1BlankEnd = 0x7, Field1BlankStart = 0x3, * Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1 */ + height = 625; /* framelines for PAL */ + ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN, CSI_CCIR_CODE_1); ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2); ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3); - } else if (mbus_fmt->width == 720 && mbus_fmt->height == 480) { /* * NTSC case @@ -422,6 +418,8 @@ int ipu_csi_init_interface(struct ipu_csi *csi, * Field1BlankEnd = 0x6, Field1BlankStart = 0x2, * Field1ActiveEnd = 0x4, Field1ActiveStart = 0 */ + height = 525; /* framelines for NTSC */ + ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN, CSI_CCIR_CODE_1); ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2); @@ -447,6 +445,10 @@ int ipu_csi_init_interface(struct ipu_csi *csi, break; } + /* Setup sensor frame size */ + ipu_csi_write(csi, (width - 1) | ((height - 1) << 16), + CSI_SENS_FRM_SIZE); + dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n", ipu_csi_read(csi, CSI_SENS_CONF)); dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n", diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index 1dcb96ccda66..1a37afcd85bd 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -160,6 +160,7 @@ struct ipu_ic_priv { spinlock_t lock; struct ipu_soc *ipu; int use_count; + int irt_use_count; struct ipu_ic task[IC_NUM_TASKS]; }; @@ -379,8 +380,6 @@ void ipu_ic_task_disable(struct ipu_ic *ic) ipu_ic_write(ic, ic_conf, IC_CONF); - ic->rotation = ic->graphics = false; - spin_unlock_irqrestore(&priv->lock, flags); } EXPORT_SYMBOL_GPL(ipu_ic_task_disable); @@ -629,22 +628,41 @@ unlock: } EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init); +static void ipu_irt_enable(struct ipu_ic *ic) +{ + struct ipu_ic_priv *priv = ic->priv; + + if (!priv->irt_use_count) + ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN); + + priv->irt_use_count++; +} + +static void ipu_irt_disable(struct ipu_ic *ic) +{ + struct ipu_ic_priv *priv = ic->priv; + + if (priv->irt_use_count) { + if (!--priv->irt_use_count) + ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN); + } +} + int ipu_ic_enable(struct ipu_ic *ic) { struct ipu_ic_priv *priv = ic->priv; unsigned long flags; - u32 module = IPU_CONF_IC_EN; spin_lock_irqsave(&priv->lock, flags); - if (ic->rotation) - module |= IPU_CONF_ROT_EN; - if (!priv->use_count) - ipu_module_enable(priv->ipu, module); + ipu_module_enable(priv->ipu, IPU_CONF_IC_EN); priv->use_count++; + if (ic->rotation) + ipu_irt_enable(ic); + spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -655,18 +673,22 @@ int ipu_ic_disable(struct ipu_ic *ic) { struct ipu_ic_priv *priv = ic->priv; unsigned long flags; - u32 module = IPU_CONF_IC_EN | IPU_CONF_ROT_EN; spin_lock_irqsave(&priv->lock, flags); priv->use_count--; if (!priv->use_count) - ipu_module_disable(priv->ipu, module); + ipu_module_disable(priv->ipu, IPU_CONF_IC_EN); if (priv->use_count < 0) priv->use_count = 0; + if (ic->rotation) + ipu_irt_disable(ic); + + ic->rotation = ic->graphics = false; + spin_unlock_irqrestore(&priv->lock, flags); return 0; diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h index bfb1e8a4483f..fd47f8f555cd 100644 --- a/drivers/gpu/ipu-v3/ipu-prv.h +++ b/drivers/gpu/ipu-v3/ipu-prv.h @@ -152,6 +152,7 @@ struct ipu_soc { void __iomem *cm_reg; void __iomem *idmac_reg; + int id; int usecount; struct clk *clk; |