diff options
Diffstat (limited to 'drivers/gpu/ipu-v3')
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-common.c | 74 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-cpmem.c | 87 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-csi.c | 5 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-dc.c | 15 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-di.c | 129 |
5 files changed, 205 insertions, 105 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index e5a38d202..f2e13eb83 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -28,6 +28,7 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <drm/drm_fourcc.h> @@ -57,10 +58,15 @@ EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) { switch (drm_fourcc) { + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: case DRM_FORMAT_RGB565: case DRM_FORMAT_BGR565: case DRM_FORMAT_RGB888: case DRM_FORMAT_BGR888: + case DRM_FORMAT_ARGB4444: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: case DRM_FORMAT_RGBX8888: @@ -988,12 +994,26 @@ static void platform_device_unregister_children(struct platform_device *pdev) struct ipu_platform_reg { struct ipu_client_platformdata pdata; const char *name; - int reg_offset; }; +/* These must be in the order of the corresponding device tree port nodes */ static const struct ipu_platform_reg client_reg[] = { { .pdata = { + .csi = 0, + .dma[0] = IPUV3_CHANNEL_CSI0, + .dma[1] = -EINVAL, + }, + .name = "imx-ipuv3-camera", + }, { + .pdata = { + .csi = 1, + .dma[0] = IPUV3_CHANNEL_CSI1, + .dma[1] = -EINVAL, + }, + .name = "imx-ipuv3-camera", + }, { + .pdata = { .di = 0, .dc = 5, .dp = IPU_DP_FLOW_SYNC_BG, @@ -1010,22 +1030,6 @@ static const struct ipu_platform_reg client_reg[] = { .dma[1] = -EINVAL, }, .name = "imx-ipuv3-crtc", - }, { - .pdata = { - .csi = 0, - .dma[0] = IPUV3_CHANNEL_CSI0, - .dma[1] = -EINVAL, - }, - .reg_offset = IPU_CM_CSI0_REG_OFS, - .name = "imx-ipuv3-camera", - }, { - .pdata = { - .csi = 1, - .dma[0] = IPUV3_CHANNEL_CSI1, - .dma[1] = -EINVAL, - }, - .reg_offset = IPU_CM_CSI1_REG_OFS, - .name = "imx-ipuv3-camera", }, }; @@ -1046,22 +1050,30 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) for (i = 0; i < ARRAY_SIZE(client_reg); i++) { const struct ipu_platform_reg *reg = &client_reg[i]; struct platform_device *pdev; - struct resource res; - - if (reg->reg_offset) { - memset(&res, 0, sizeof(res)); - res.flags = IORESOURCE_MEM; - res.start = ipu_base + ipu->devtype->cm_ofs + reg->reg_offset; - res.end = res.start + PAGE_SIZE - 1; - pdev = platform_device_register_resndata(dev, reg->name, - id++, &res, 1, ®->pdata, sizeof(reg->pdata)); - } else { - pdev = platform_device_register_data(dev, reg->name, - id++, ®->pdata, sizeof(reg->pdata)); + + pdev = platform_device_alloc(reg->name, id++); + if (!pdev) { + ret = -ENOMEM; + goto err_register; + } + + pdev->dev.parent = dev; + + /* Associate subdevice with the corresponding port node */ + pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i); + if (!pdev->dev.of_node) { + dev_err(dev, "missing port@%d node in %s\n", i, + dev->of_node->full_name); + ret = -ENODEV; + goto err_register; } - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); + ret = platform_device_add_data(pdev, ®->pdata, + sizeof(reg->pdata)); + if (!ret) + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); goto err_register; } } diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index 3bf05bc4a..63eb16bf2 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c @@ -452,7 +452,7 @@ void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); -static const struct ipu_rgb def_rgb_32 = { +static const struct ipu_rgb def_xrgb_32 = { .red = { .offset = 16, .length = 8, }, .green = { .offset = 8, .length = 8, }, .blue = { .offset = 0, .length = 8, }, @@ -460,7 +460,7 @@ static const struct ipu_rgb def_rgb_32 = { .bits_per_pixel = 32, }; -static const struct ipu_rgb def_bgr_32 = { +static const struct ipu_rgb def_xbgr_32 = { .red = { .offset = 0, .length = 8, }, .green = { .offset = 8, .length = 8, }, .blue = { .offset = 16, .length = 8, }, @@ -468,6 +468,22 @@ static const struct ipu_rgb def_bgr_32 = { .bits_per_pixel = 32, }; +static const struct ipu_rgb def_rgbx_32 = { + .red = { .offset = 24, .length = 8, }, + .green = { .offset = 16, .length = 8, }, + .blue = { .offset = 8, .length = 8, }, + .transp = { .offset = 0, .length = 8, }, + .bits_per_pixel = 32, +}; + +static const struct ipu_rgb def_bgrx_32 = { + .red = { .offset = 8, .length = 8, }, + .green = { .offset = 16, .length = 8, }, + .blue = { .offset = 24, .length = 8, }, + .transp = { .offset = 0, .length = 8, }, + .bits_per_pixel = 32, +}; + static const struct ipu_rgb def_rgb_24 = { .red = { .offset = 16, .length = 8, }, .green = { .offset = 8, .length = 8, }, @@ -500,6 +516,46 @@ static const struct ipu_rgb def_bgr_16 = { .bits_per_pixel = 16, }; +static const struct ipu_rgb def_argb_16 = { + .red = { .offset = 10, .length = 5, }, + .green = { .offset = 5, .length = 5, }, + .blue = { .offset = 0, .length = 5, }, + .transp = { .offset = 15, .length = 1, }, + .bits_per_pixel = 16, +}; + +static const struct ipu_rgb def_argb_16_4444 = { + .red = { .offset = 8, .length = 4, }, + .green = { .offset = 4, .length = 4, }, + .blue = { .offset = 0, .length = 4, }, + .transp = { .offset = 12, .length = 4, }, + .bits_per_pixel = 16, +}; + +static const struct ipu_rgb def_abgr_16 = { + .red = { .offset = 0, .length = 5, }, + .green = { .offset = 5, .length = 5, }, + .blue = { .offset = 10, .length = 5, }, + .transp = { .offset = 15, .length = 1, }, + .bits_per_pixel = 16, +}; + +static const struct ipu_rgb def_rgba_16 = { + .red = { .offset = 11, .length = 5, }, + .green = { .offset = 6, .length = 5, }, + .blue = { .offset = 1, .length = 5, }, + .transp = { .offset = 0, .length = 1, }, + .bits_per_pixel = 16, +}; + +static const struct ipu_rgb def_bgra_16 = { + .red = { .offset = 1, .length = 5, }, + .green = { .offset = 6, .length = 5, }, + .blue = { .offset = 11, .length = 5, }, + .transp = { .offset = 0, .length = 1, }, + .bits_per_pixel = 16, +}; + #define Y_OFFSET(pix, x, y) ((x) + pix->width * (y)) #define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ (pix->width * (y) / 4) + (x) / 2) @@ -563,11 +619,19 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc) break; case DRM_FORMAT_ABGR8888: case DRM_FORMAT_XBGR8888: - ipu_cpmem_set_format_rgb(ch, &def_bgr_32); + ipu_cpmem_set_format_rgb(ch, &def_xbgr_32); break; case DRM_FORMAT_ARGB8888: case DRM_FORMAT_XRGB8888: - ipu_cpmem_set_format_rgb(ch, &def_rgb_32); + ipu_cpmem_set_format_rgb(ch, &def_xrgb_32); + break; + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + ipu_cpmem_set_format_rgb(ch, &def_rgbx_32); + break; + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_BGRX8888: + ipu_cpmem_set_format_rgb(ch, &def_bgrx_32); break; case DRM_FORMAT_BGR888: ipu_cpmem_set_format_rgb(ch, &def_bgr_24); @@ -581,6 +645,21 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc) case DRM_FORMAT_BGR565: ipu_cpmem_set_format_rgb(ch, &def_bgr_16); break; + case DRM_FORMAT_ARGB1555: + ipu_cpmem_set_format_rgb(ch, &def_argb_16); + break; + case DRM_FORMAT_ABGR1555: + ipu_cpmem_set_format_rgb(ch, &def_abgr_16); + break; + case DRM_FORMAT_RGBA5551: + ipu_cpmem_set_format_rgb(ch, &def_rgba_16); + break; + case DRM_FORMAT_BGRA5551: + ipu_cpmem_set_format_rgb(ch, &def_bgra_16); + break; + case DRM_FORMAT_ARGB4444: + ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444); + break; default: return -EINVAL; } diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index 752cdd2da..06631ac61 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c @@ -202,7 +202,7 @@ static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk, u32 ipu_clk) { u32 temp; - u32 div_ratio; + int div_ratio; div_ratio = (ipu_clk / pixel_clk) - 1; @@ -271,6 +271,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code) case MEDIA_BUS_FMT_SGBRG8_1X8: case MEDIA_BUS_FMT_SGRBG8_1X8: case MEDIA_BUS_FMT_SRGGB8_1X8: + case MEDIA_BUS_FMT_Y8_1X8: cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; cfg->mipi_dt = MIPI_DT_RAW8; cfg->data_width = IPU_CSI_DATA_WIDTH_8; @@ -538,7 +539,7 @@ void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active, temp = ipu_csi_read(csi, CSI_TST_CTRL); - if (active == false) { + if (!active) { temp &= ~CSI_TEST_GEN_MODE_EN; ipu_csi_write(csi, temp, CSI_TST_CTRL); } else { diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index 9ef2e1f54..d3ad53473 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -183,12 +183,19 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, } if (interlaced) { - dc_link_event(dc, DC_EVT_NL, 0, 3); - dc_link_event(dc, DC_EVT_EOL, 0, 2); - dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1); + int addr; + + if (dc->di) + addr = 1; + else + addr = 0; + + dc_link_event(dc, DC_EVT_NL, addr, 3); + dc_link_event(dc, DC_EVT_EOL, addr, 2); + dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1); /* Init template microcode */ - dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1); + dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, 6, 1); } else { if (dc->di) { dc_link_event(dc, DC_EVT_NL, 2, 3); diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c index 2970c6bb6..359268e3a 100644 --- a/drivers/gpu/ipu-v3/ipu-di.c +++ b/drivers/gpu/ipu-v3/ipu-di.c @@ -71,6 +71,10 @@ enum di_sync_wave { DI_SYNC_HSYNC = 3, DI_SYNC_VSYNC = 4, DI_SYNC_DE = 6, + + DI_SYNC_CNT1 = 2, /* counter >= 2 only */ + DI_SYNC_CNT4 = 5, /* counter >= 5 only */ + DI_SYNC_CNT5 = 6, /* counter >= 6 only */ }; #define SYNC_WAVE 0 @@ -211,66 +215,59 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di, sig->mode.hback_porch + sig->mode.hfront_porch; u32 v_total = sig->mode.vactive + sig->mode.vsync_len + sig->mode.vback_porch + sig->mode.vfront_porch; - u32 reg; struct di_sync_config cfg[] = { { - .run_count = h_total / 2 - 1, - .run_src = DI_SYNC_CLK, + /* 1: internal VSYNC for each frame */ + .run_count = v_total * 2 - 1, + .run_src = 3, /* == counter 7 */ }, { - .run_count = h_total - 11, + /* PIN2: HSYNC waveform */ + .run_count = h_total - 1, .run_src = DI_SYNC_CLK, - .cnt_down = 4, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_CLK, + .cnt_down = sig->mode.hsync_len * 2, }, { - .run_count = v_total * 2 - 1, - .run_src = DI_SYNC_INT_HSYNC, - .offset_count = 1, - .offset_src = DI_SYNC_INT_HSYNC, - .cnt_down = 4, + /* PIN3: VSYNC waveform */ + .run_count = v_total - 1, + .run_src = 4, /* == counter 7 */ + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = 4, /* == counter 7 */ + .cnt_down = sig->mode.vsync_len * 2, + .cnt_clr_src = DI_SYNC_CNT1, }, { - .run_count = v_total / 2 - 1, + /* 4: Field */ + .run_count = v_total / 2, .run_src = DI_SYNC_HSYNC, - .offset_count = sig->mode.vback_porch, - .offset_src = DI_SYNC_HSYNC, + .offset_count = h_total / 2, + .offset_src = DI_SYNC_CLK, .repeat_count = 2, - .cnt_clr_src = DI_SYNC_VSYNC, - }, { - .run_src = DI_SYNC_HSYNC, - .repeat_count = sig->mode.vactive / 2, - .cnt_clr_src = 4, - }, { - .run_count = v_total - 1, - .run_src = DI_SYNC_HSYNC, + .cnt_clr_src = DI_SYNC_CNT1, }, { - .run_count = v_total / 2 - 1, + /* 5: Active lines */ .run_src = DI_SYNC_HSYNC, - .offset_count = 9, + .offset_count = (sig->mode.vsync_len + + sig->mode.vback_porch) / 2, .offset_src = DI_SYNC_HSYNC, - .repeat_count = 2, - .cnt_clr_src = DI_SYNC_VSYNC, + .repeat_count = sig->mode.vactive / 2, + .cnt_clr_src = DI_SYNC_CNT4, }, { + /* 6: Active pixel, referenced by DC */ .run_src = DI_SYNC_CLK, - .offset_count = sig->mode.hback_porch, + .offset_count = sig->mode.hsync_len + + sig->mode.hback_porch, .offset_src = DI_SYNC_CLK, .repeat_count = sig->mode.hactive, - .cnt_clr_src = 5, + .cnt_clr_src = DI_SYNC_CNT5, }, { - .run_count = v_total - 1, - .run_src = DI_SYNC_INT_HSYNC, - .offset_count = v_total / 2, - .offset_src = DI_SYNC_INT_HSYNC, - .cnt_clr_src = DI_SYNC_HSYNC, - .cnt_down = 4, + /* 7: Half line HSYNC */ + .run_count = h_total / 2 - 1, + .run_src = DI_SYNC_CLK, } }; ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); - /* set gentime select and tag sel */ - reg = ipu_di_read(di, DI_SW_GEN1(9)); - reg &= 0x1FFFFFFF; - reg |= (3 - 1) << 29 | 0x00008000; - ipu_di_write(di, reg, DI_SW_GEN1(9)); - ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF); } @@ -543,6 +540,29 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode) } EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode); +static u32 ipu_di_gen_polarity(int pin) +{ + switch (pin) { + case 1: + return DI_GEN_POLARITY_1; + case 2: + return DI_GEN_POLARITY_2; + case 3: + return DI_GEN_POLARITY_3; + case 4: + return DI_GEN_POLARITY_4; + case 5: + return DI_GEN_POLARITY_5; + case 6: + return DI_GEN_POLARITY_6; + case 7: + return DI_GEN_POLARITY_7; + case 8: + return DI_GEN_POLARITY_8; + } + return 0; +} + int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) { u32 reg; @@ -582,15 +602,8 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) /* set y_sel = 1 */ di_gen |= 0x10000000; - di_gen |= DI_GEN_POLARITY_5; - di_gen |= DI_GEN_POLARITY_8; - - vsync_cnt = 7; - if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) - di_gen |= DI_GEN_POLARITY_3; - if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) - di_gen |= DI_GEN_POLARITY_2; + vsync_cnt = 3; } else { ipu_di_sync_config_noninterlaced(di, sig, div); @@ -602,25 +615,13 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) */ if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3)) vsync_cnt = 6; - - if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) { - if (sig->hsync_pin == 2) - di_gen |= DI_GEN_POLARITY_2; - else if (sig->hsync_pin == 4) - di_gen |= DI_GEN_POLARITY_4; - else if (sig->hsync_pin == 7) - di_gen |= DI_GEN_POLARITY_7; - } - if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) { - if (sig->vsync_pin == 3) - di_gen |= DI_GEN_POLARITY_3; - else if (sig->vsync_pin == 6) - di_gen |= DI_GEN_POLARITY_6; - else if (sig->vsync_pin == 8) - di_gen |= DI_GEN_POLARITY_8; - } } + if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) + di_gen |= ipu_di_gen_polarity(sig->hsync_pin); + if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) + di_gen |= ipu_di_gen_polarity(sig->vsync_pin); + if (sig->clk_pol) di_gen |= DI_GEN_POLARITY_DISP_CLK; |