drm/imx: cleanup and csi improvements
- Remove the unused struct imx_drm_crtc and the unused pipes field from imx_drm_device and replace drm_dev_unref with drm_dev_put. - Extend CSI configuration to support RGB888 and BGR888 capture, as well as 16-bit RGB565 capture via a parallel bus. - Add CPMEM support for negative interlace offsets, which is necessary to support writing captured bottom-top interlaced fields to memory with interleaved lines. -----BEGIN PGP SIGNATURE----- iI4EABYIADYWIQRRO6F6WdpH1R0vGibVhaclGDdiwAUCW1G7LxgccGhpbGlwcC56 YWJlbEBnbWFpbC5jb20ACgkQ1YWnJRg3YsBNlQD9FofVPjKCFW79jy/H2bf+hWVB uGhLAxfSsHmLLUSi7Z8A/jFtafSMQDU8uNNbTTHNjofKiFqdjpUljCUgTuA1paUC =oPJE -----END PGP SIGNATURE----- Merge tag 'imx-drm-next-2018-07-20' of git://git.pengutronix.de/git/pza/linux into drm-next drm/imx: cleanup and csi improvements - Remove the unused struct imx_drm_crtc and the unused pipes field from imx_drm_device and replace drm_dev_unref with drm_dev_put. - Extend CSI configuration to support RGB888 and BGR888 capture, as well as 16-bit RGB565 capture via a parallel bus. - Add CPMEM support for negative interlace offsets, which is necessary to support writing captured bottom-top interlaced fields to memory with interleaved lines. Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/1532100583.3438.9.camel@pengutronix.de
This commit is contained in:
commit
a6f6cdefd4
@ -37,7 +37,6 @@
|
||||
|
||||
struct imx_drm_device {
|
||||
struct drm_device *drm;
|
||||
unsigned int pipes;
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
@ -229,7 +228,7 @@ static int imx_drm_bind(struct device *dev)
|
||||
imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);
|
||||
if (!imxdrm) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unref;
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
imxdrm->drm = drm;
|
||||
@ -306,8 +305,8 @@ static int imx_drm_bind(struct device *dev)
|
||||
component_unbind_all(drm->dev, drm);
|
||||
err_kms:
|
||||
drm_mode_config_cleanup(drm);
|
||||
err_unref:
|
||||
drm_dev_unref(drm);
|
||||
err_put:
|
||||
drm_dev_put(drm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -327,7 +326,7 @@ static void imx_drm_unbind(struct device *dev)
|
||||
component_unbind_all(drm->dev, drm);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
drm_dev_unref(drm);
|
||||
drm_dev_put(drm);
|
||||
}
|
||||
|
||||
static const struct component_master_ops imx_drm_ops = {
|
||||
|
@ -10,7 +10,6 @@ struct drm_display_mode;
|
||||
struct drm_encoder;
|
||||
struct drm_framebuffer;
|
||||
struct drm_plane;
|
||||
struct imx_drm_crtc;
|
||||
struct platform_device;
|
||||
|
||||
struct imx_crtc_state {
|
||||
|
@ -611,6 +611,9 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
||||
return PTR_ERR(imx_ldb->regmap);
|
||||
}
|
||||
|
||||
/* disable LDB by resetting the control register to POR default */
|
||||
regmap_write(imx_ldb->regmap, IOMUXC_GPR2, 0);
|
||||
|
||||
imx_ldb->dev = dev;
|
||||
|
||||
if (of_id)
|
||||
@ -651,14 +654,14 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret || i < 0 || i > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (!of_device_is_available(child))
|
||||
continue;
|
||||
|
||||
if (dual && i > 0) {
|
||||
dev_warn(dev, "dual-channel mode, ignoring second output\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(child))
|
||||
continue;
|
||||
|
||||
channel = &imx_ldb->channel[i];
|
||||
channel->ldb = imx_ldb;
|
||||
channel->chno = i;
|
||||
|
@ -35,7 +35,6 @@
|
||||
struct ipu_crtc {
|
||||
struct device *dev;
|
||||
struct drm_crtc base;
|
||||
struct imx_drm_crtc *imx_crtc;
|
||||
|
||||
/* plane[0] is the full plane, plane[1] is the partial plane */
|
||||
struct ipu_plane *plane[2];
|
||||
|
@ -269,9 +269,20 @@ EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
|
||||
|
||||
void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
|
||||
{
|
||||
u32 ilo, sly;
|
||||
|
||||
if (stride < 0) {
|
||||
stride = -stride;
|
||||
ilo = 0x100000 - (stride / 8);
|
||||
} else {
|
||||
ilo = stride / 8;
|
||||
}
|
||||
|
||||
sly = (stride * 2) - 1;
|
||||
|
||||
ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
|
||||
ipu_ch_param_write_field(ch, IPU_FIELD_ILO, stride / 8);
|
||||
ipu_ch_param_write_field(ch, IPU_FIELD_SLY, (stride * 2) - 1);
|
||||
ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
|
||||
ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
|
||||
|
||||
|
@ -224,14 +224,18 @@ static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
|
||||
* Find the CSI data format and data width for the given V4L2 media
|
||||
* bus pixel format code.
|
||||
*/
|
||||
static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code)
|
||||
static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
|
||||
enum v4l2_mbus_type mbus_type)
|
||||
{
|
||||
switch (mbus_code) {
|
||||
case MEDIA_BUS_FMT_BGR565_2X8_BE:
|
||||
case MEDIA_BUS_FMT_BGR565_2X8_LE:
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_BE:
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_LE:
|
||||
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
|
||||
if (mbus_type == V4L2_MBUS_CSI2)
|
||||
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
|
||||
else
|
||||
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
|
||||
cfg->mipi_dt = MIPI_DT_RGB565;
|
||||
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
|
||||
break;
|
||||
@ -247,6 +251,12 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code)
|
||||
cfg->mipi_dt = MIPI_DT_RGB555;
|
||||
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
case MEDIA_BUS_FMT_BGR888_1X24:
|
||||
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
|
||||
cfg->mipi_dt = MIPI_DT_RGB888;
|
||||
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
|
||||
cfg->mipi_dt = MIPI_DT_YUV422;
|
||||
@ -318,13 +328,17 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code)
|
||||
/*
|
||||
* Fill a CSI bus config struct from mbus_config and mbus_framefmt.
|
||||
*/
|
||||
static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
|
||||
static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
|
||||
struct v4l2_mbus_config *mbus_cfg,
|
||||
struct v4l2_mbus_framefmt *mbus_fmt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(csicfg, 0, sizeof(*csicfg));
|
||||
|
||||
mbus_code_to_bus_cfg(csicfg, mbus_fmt->code);
|
||||
ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (mbus_cfg->type) {
|
||||
case V4L2_MBUS_PARALLEL:
|
||||
@ -339,7 +353,8 @@ static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
|
||||
break;
|
||||
case V4L2_MBUS_BT656:
|
||||
csicfg->ext_vsync = 0;
|
||||
if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field))
|
||||
if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
|
||||
mbus_fmt->field == V4L2_FIELD_ALTERNATE)
|
||||
csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
|
||||
else
|
||||
csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
|
||||
@ -355,6 +370,8 @@ static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
|
||||
/* will never get here, keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipu_csi_init_interface(struct ipu_csi *csi,
|
||||
@ -364,8 +381,11 @@ int ipu_csi_init_interface(struct ipu_csi *csi,
|
||||
struct ipu_csi_bus_config cfg;
|
||||
unsigned long flags;
|
||||
u32 width, height, data = 0;
|
||||
int ret;
|
||||
|
||||
fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt);
|
||||
ret = fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* set default sensor frame width and height */
|
||||
width = mbus_fmt->width;
|
||||
@ -586,11 +606,14 @@ int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
|
||||
struct ipu_csi_bus_config cfg;
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
int ret;
|
||||
|
||||
if (vc > 3)
|
||||
return -EINVAL;
|
||||
|
||||
mbus_code_to_bus_cfg(&cfg, mbus_fmt->code);
|
||||
ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&csi->lock, flags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user