Commit e1db7043 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

[media] V4L: sh_mobile_ceu_camera: convert to the new mbus-config subdev operations

Switch from soc-camera specific .{query,set}_bus_param() to V4L2
subdevice .[gs]_mbus_config() operations.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 679419aa
...@@ -144,30 +144,6 @@ static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb) ...@@ -144,30 +144,6 @@ static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
return container_of(vb, struct sh_mobile_ceu_buffer, vb); return container_of(vb, struct sh_mobile_ceu_buffer, vb);
} }
static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
{
unsigned long flags;
flags = SOCAM_MASTER |
SOCAM_PCLK_SAMPLE_RISING |
SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_HSYNC_ACTIVE_LOW |
SOCAM_VSYNC_ACTIVE_HIGH |
SOCAM_VSYNC_ACTIVE_LOW |
SOCAM_DATA_ACTIVE_HIGH;
if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS)
flags |= SOCAM_DATAWIDTH_8;
if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS)
flags |= SOCAM_DATAWIDTH_16;
if (flags & SOCAM_DATAWIDTH_MASK)
return flags;
return 0;
}
static void ceu_write(struct sh_mobile_ceu_dev *priv, static void ceu_write(struct sh_mobile_ceu_dev *priv,
unsigned long reg_offs, u32 data) unsigned long reg_offs, u32 data)
{ {
...@@ -737,66 +713,90 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) ...@@ -737,66 +713,90 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr)
ceu_write(pcdev, CAPSR, capsr); ceu_write(pcdev, CAPSR, capsr);
} }
/* Find the bus subdevice driver, e.g., CSI2 */
static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev,
struct soc_camera_device *icd)
{
if (!pcdev->csi2_pdev)
return soc_camera_to_subdev(icd);
return find_csi2(pcdev);
}
#define CEU_BUS_FLAGS (V4L2_MBUS_MASTER | \
V4L2_MBUS_PCLK_SAMPLE_RISING | \
V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
V4L2_MBUS_HSYNC_ACTIVE_LOW | \
V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
V4L2_MBUS_VSYNC_ACTIVE_LOW | \
V4L2_MBUS_DATA_ACTIVE_HIGH)
/* Capture is not running, no interrupts, no locking needed */ /* Capture is not running, no interrupts, no locking needed */
static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
__u32 pixfmt) __u32 pixfmt)
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_dev *pcdev = ici->priv;
int ret; struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
unsigned long camera_flags, common_flags, value;
int yuv_lineskip;
struct sh_mobile_ceu_cam *cam = icd->host_priv; struct sh_mobile_ceu_cam *cam = icd->host_priv;
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
unsigned long value, common_flags = CEU_BUS_FLAGS;
u32 capsr = capture_save_reset(pcdev); u32 capsr = capture_save_reset(pcdev);
unsigned int yuv_lineskip;
int ret;
camera_flags = icd->ops->query_bus_param(icd); /*
common_flags = soc_camera_bus_param_compatible(camera_flags, * If the client doesn't implement g_mbus_config, we just use our
make_bus_param(pcdev)); * platform data
if (!common_flags) */
return -EINVAL; ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
if (!ret) {
common_flags = soc_mbus_config_compatible(&cfg,
common_flags);
if (!common_flags)
return -EINVAL;
} else if (ret != -ENOIOCTLCMD) {
return ret;
}
/* Make choises, based on platform preferences */ /* Make choises, based on platform preferences */
if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
(common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW) if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW)
common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
else else
common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
} }
if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
(common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW) if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW)
common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
else else
common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
} }
ret = icd->ops->set_bus_param(icd, common_flags); cfg.flags = common_flags;
if (ret < 0) ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret; return ret;
switch (common_flags & SOCAM_DATAWIDTH_MASK) { if (icd->current_fmt->host_fmt->bits_per_sample > 8)
case SOCAM_DATAWIDTH_8:
pcdev->is_16bit = 0;
break;
case SOCAM_DATAWIDTH_16:
pcdev->is_16bit = 1; pcdev->is_16bit = 1;
break; else
default: pcdev->is_16bit = 0;
return -EINVAL;
}
ceu_write(pcdev, CRCNTR, 0); ceu_write(pcdev, CRCNTR, 0);
ceu_write(pcdev, CRCMPR, 0); ceu_write(pcdev, CRCMPR, 0);
value = 0x00000010; /* data fetch by default */ value = 0x00000010; /* data fetch by default */
yuv_lineskip = 0; yuv_lineskip = 0x10;
switch (icd->current_fmt->host_fmt->fourcc) { switch (icd->current_fmt->host_fmt->fourcc) {
case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV21:
yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ /* convert 4:2:2 -> 4:2:0 */
yuv_lineskip = 0; /* skip for NV12/21, no skip for NV16/61 */
/* fall-through */ /* fall-through */
case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61: case V4L2_PIX_FMT_NV61:
...@@ -822,8 +822,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ...@@ -822,8 +822,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61) icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61)
value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */
value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
value |= pcdev->is_16bit ? 1 << 12 : 0; value |= pcdev->is_16bit ? 1 << 12 : 0;
/* CSI2 mode */ /* CSI2 mode */
...@@ -866,9 +866,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ...@@ -866,9 +866,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
* using 7 we swap the data bytes to match the incoming order: * using 7 we swap the data bytes to match the incoming order:
* D0, D1, D2, D3, D4, D5, D6, D7 * D0, D1, D2, D3, D4, D5, D6, D7
*/ */
value = 0x00000017; value = 0x00000007 | yuv_lineskip;
if (yuv_lineskip)
value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */
ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CDOCR, value);
ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
...@@ -889,13 +887,19 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, ...@@ -889,13 +887,19 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_dev *pcdev = ici->priv;
unsigned long camera_flags, common_flags; struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
unsigned long common_flags = CEU_BUS_FLAGS;
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
int ret;
camera_flags = icd->ops->query_bus_param(icd); ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
common_flags = soc_camera_bus_param_compatible(camera_flags, if (!ret)
make_bus_param(pcdev)); common_flags = soc_mbus_config_compatible(&cfg,
if (!common_flags || buswidth > 16 || common_flags);
(buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16))) else if (ret != -ENOIOCTLCMD)
return ret;
if (!common_flags || buswidth > 16)
return -EINVAL; return -EINVAL;
return 0; return 0;
...@@ -905,26 +909,26 @@ static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = { ...@@ -905,26 +909,26 @@ static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = {
{ {
.fourcc = V4L2_PIX_FMT_NV12, .fourcc = V4L2_PIX_FMT_NV12,
.name = "NV12", .name = "NV12",
.bits_per_sample = 12, .bits_per_sample = 8,
.packing = SOC_MBUS_PACKING_NONE, .packing = SOC_MBUS_PACKING_1_5X8,
.order = SOC_MBUS_ORDER_LE, .order = SOC_MBUS_ORDER_LE,
}, { }, {
.fourcc = V4L2_PIX_FMT_NV21, .fourcc = V4L2_PIX_FMT_NV21,
.name = "NV21", .name = "NV21",
.bits_per_sample = 12, .bits_per_sample = 8,
.packing = SOC_MBUS_PACKING_NONE, .packing = SOC_MBUS_PACKING_1_5X8,
.order = SOC_MBUS_ORDER_LE, .order = SOC_MBUS_ORDER_LE,
}, { }, {
.fourcc = V4L2_PIX_FMT_NV16, .fourcc = V4L2_PIX_FMT_NV16,
.name = "NV16", .name = "NV16",
.bits_per_sample = 16, .bits_per_sample = 8,
.packing = SOC_MBUS_PACKING_NONE, .packing = SOC_MBUS_PACKING_2X8_PADHI,
.order = SOC_MBUS_ORDER_LE, .order = SOC_MBUS_ORDER_LE,
}, { }, {
.fourcc = V4L2_PIX_FMT_NV61, .fourcc = V4L2_PIX_FMT_NV61,
.name = "NV61", .name = "NV61",
.bits_per_sample = 16, .bits_per_sample = 8,
.packing = SOC_MBUS_PACKING_NONE, .packing = SOC_MBUS_PACKING_2X8_PADHI,
.order = SOC_MBUS_ORDER_LE, .order = SOC_MBUS_ORDER_LE,
}, },
}; };
...@@ -933,6 +937,8 @@ static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = { ...@@ -933,6 +937,8 @@ static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = {
static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
{ {
return fmt->packing == SOC_MBUS_PACKING_NONE || return fmt->packing == SOC_MBUS_PACKING_NONE ||
(fmt->bits_per_sample == 8 &&
fmt->packing == SOC_MBUS_PACKING_1_5X8) ||
(fmt->bits_per_sample == 8 && (fmt->bits_per_sample == 8 &&
fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
(fmt->bits_per_sample > 8 && (fmt->bits_per_sample > 8 &&
...@@ -966,6 +972,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int ...@@ -966,6 +972,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
} }
if (!pcdev->pdata->csi2) { if (!pcdev->pdata->csi2) {
/* Are there any restrictions in the CSI-2 case? */
ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
if (ret < 0) if (ret < 0)
return 0; return 0;
...@@ -1626,8 +1633,6 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, ...@@ -1626,8 +1633,6 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
bool image_mode; bool image_mode;
enum v4l2_field field; enum v4l2_field field;
dev_geo(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height);
switch (pix->field) { switch (pix->field) {
default: default:
pix->field = V4L2_FIELD_NONE; pix->field = V4L2_FIELD_NONE;
...@@ -1665,6 +1670,9 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, ...@@ -1665,6 +1670,9 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
image_mode = false; image_mode = false;
} }
dev_info(dev, "S_FMT(pix=0x%x, fld 0x%x, code 0x%x, %ux%u)\n", pixfmt, mf.field, mf.code,
pix->width, pix->height);
dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height);
/* 5. - 9. */ /* 5. - 9. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment