From: Sascha Hauer <s.hauer@pengutronix.de>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH 11/13] video: ipuv3: Replace ipu_output with VPL
Date: Thu, 9 Jul 2015 09:24:15 +0200 [thread overview]
Message-ID: <1436426657-5266-12-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1436426657-5266-1-git-send-email-s.hauer@pengutronix.de>
The ipuv3 makes heavy use of video encoders internally to the SoC but
also external encoders are common. Switch to VPL support to be able
to handle these properly.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/video/imx-ipu-v3/Kconfig | 1 +
drivers/video/imx-ipu-v3/imx-hdmi.c | 93 +++++++++++-----------
drivers/video/imx-ipu-v3/imx-ipu-v3.h | 24 ++----
drivers/video/imx-ipu-v3/imx-ldb.c | 116 +++++++++++++++++++++-------
drivers/video/imx-ipu-v3/ipufb.c | 141 ++++++++++++++--------------------
5 files changed, 197 insertions(+), 178 deletions(-)
diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
index 2ca9132..386ff5b 100644
--- a/drivers/video/imx-ipu-v3/Kconfig
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -1,6 +1,7 @@
config DRIVER_VIDEO_IMX_IPUV3
bool "i.MX IPUv3 driver"
depends on ARCH_IMX
+ select VIDEO_VPL
help
Support the IPUv3 found on Freescale i.MX51/53/6 SoCs
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c
index e01bfe8..f5a2e3c 100644
--- a/drivers/video/imx-ipu-v3/imx-hdmi.c
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -23,6 +23,7 @@
#include <asm-generic/div64.h>
#include <linux/clk.h>
#include <i2c/i2c.h>
+#include <video/vpl.h>
#include <mach/imx6-regs.h>
#include <mach/imx53-regs.h>
@@ -133,13 +134,13 @@ struct imx_hdmi {
bool phy_enabled;
struct regmap *regmap;
- struct i2c_adapter *ddc;
+ struct device_node *ddc_node;;
void __iomem *regs;
unsigned int sample_rate;
int ratio;
- struct ipu_output output;
+ struct vpl vpl;
};
static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
@@ -1011,7 +1012,7 @@ static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
}
-static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct fb_videomode *mode)
+static int imx_hdmi_setup(struct imx_hdmi *hdmi)
{
int ret;
@@ -1134,43 +1135,58 @@ static struct of_device_id imx_hdmi_dt_ids[] = {
}
};
-static int imx_hdmi_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, struct display_timings *timings)
{
- struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+ int ret = -ENOENT;
- imx_hdmi_set_ipu_di_mux(hdmi, di);
+ if (hdmi->ddc_node) {
+ struct i2c_adapter *i2c;
- return 0;
-}
+ i2c = of_find_i2c_adapter_by_node(hdmi->ddc_node);
+ if (!i2c)
+ return -ENODEV;
+ timings->edid = edid_read_i2c(i2c);
+ if (!timings->edid)
+ return -EINVAL;
-static int imx_hdmi_commit(struct ipu_output *output, struct fb_videomode *mode, int di)
-{
- struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
-
- imx_hdmi_setup(hdmi, mode);
+ ret = edid_to_display_timings(timings, timings->edid);
+ }
- return 0;
+ return ret;
}
-static int imx_hdmi_disable(struct ipu_output *output)
+static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int port,
+ unsigned int cmd, void *data)
{
- struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
-
- imx_hdmi_phy_disable(hdmi);
+ struct imx_hdmi *hdmi = container_of(vpl, struct imx_hdmi, vpl);
+ struct ipu_di_mode *mode;
+
+ switch (cmd) {
+ case VPL_ENABLE:
+ return imx_hdmi_setup(hdmi);
+ case VPL_DISABLE:
+ imx_hdmi_phy_disable(hdmi);
+ return 0;
+ case VPL_PREPARE:
+ imx_hdmi_set_ipu_di_mux(hdmi, port);
+ return 0;
+ case VPL_GET_VIDEOMODES:
+ return imx_hdmi_get_modes(hdmi, data);
+ case IMX_IPU_VPL_DI_MODE:
+ mode = data;
+
+ mode->di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+ mode->interface_pix_fmt = V4L2_PIX_FMT_RGB24;
+
+ return 0;
+ }
return 0;
}
-static struct ipu_output_ops imx_hdmi_ops = {
- .prepare = imx_hdmi_prepare,
- .enable = imx_hdmi_commit,
- .disable = imx_hdmi_disable,
-};
-
static int imx_hdmi_probe(struct device_d *dev)
{
struct device_node *np = dev->device_node;
- struct device_node *ddc_node;
struct imx_hdmi *hdmi;
int ret;
const struct imx_hdmi_data *devtype;
@@ -1190,18 +1206,7 @@ static int imx_hdmi_probe(struct device_d *dev)
if (ret)
return ret;
- if (IS_ENABLED(CONFIG_DRIVER_VIDEO_EDID)) {
- ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
- if (ddc_node) {
- hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
- if (!hdmi->ddc)
- dev_dbg(hdmi->dev, "failed to read ddc node\n");
- } else {
- dev_dbg(hdmi->dev, "no ddc property found\n");
- }
-
- ddc_node = NULL;
- }
+ hdmi->ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
hdmi->regs = dev_request_mem_region(dev, 0);
if (!hdmi->regs)
@@ -1269,15 +1274,11 @@ static int imx_hdmi_probe(struct device_d *dev)
/* Unmute interrupts */
hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
- hdmi->output.ops = &imx_hdmi_ops;
- hdmi->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
- hdmi->output.out_pixel_fmt = V4L2_PIX_FMT_RGB24;
- hdmi->output.name = asprintf("hdmi-0");
- hdmi->output.ipu_mask = devtype->ipu_mask;
- hdmi->output.edid_i2c_adapter = hdmi->ddc;
- hdmi->output.modes = of_get_display_timings(np);
-
- ipu_register_output(&hdmi->output);
+ hdmi->vpl.node = np;
+ hdmi->vpl.ioctl = imx_hdmi_ioctl;
+ ret = vpl_register(&hdmi->vpl);
+ if (ret)
+ return ret;
return 0;
diff --git a/drivers/video/imx-ipu-v3/imx-ipu-v3.h b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
index d046aee..783535e 100644
--- a/drivers/video/imx-ipu-v3/imx-ipu-v3.h
+++ b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
@@ -14,6 +14,7 @@
#include <io.h>
#include <fb.h>
+#include <video/vpl.h>
#include <video/fourcc.h>
struct ipu_soc;
@@ -318,26 +319,11 @@ struct ipu_client_platformdata {
struct device_node *device_node;
};
-struct ipu_output;
-
-struct ipu_output_ops {
- int (*prepare)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
- int (*enable)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
- int (*disable)(struct ipu_output *ipu_video_output);
- int (*unprepare)(struct ipu_output *ipu_video_output);
-};
-
-struct ipu_output {
- struct ipu_output_ops *ops;
- struct list_head list;
- unsigned int di_clkflags;
- uint32_t out_pixel_fmt;
- struct i2c_adapter *edid_i2c_adapter;
- struct display_timings *modes;
- char *name;
- int ipu_mask;
+struct ipu_di_mode {
+ u32 di_clkflags;
+ u32 interface_pix_fmt;
};
-int ipu_register_output(struct ipu_output *ouput);
+#define IMX_IPU_VPL_DI_MODE 0x12660001
#endif /* __DRM_IPU_H__ */
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
index a05bfad..db5f8b6 100644
--- a/drivers/video/imx-ipu-v3/imx-ldb.c
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -21,10 +21,13 @@
#include <common.h>
#include <fb.h>
#include <io.h>
+#include <of_graph.h>
#include <driver.h>
#include <malloc.h>
#include <errno.h>
#include <init.h>
+#include <video/vpl.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm-generic/div64.h>
@@ -57,13 +60,17 @@ struct imx_ldb_channel {
int chno;
int mode_valid;
struct display_timings *modes;
- struct ipu_output output;
+ struct device_node *remote;
+ struct vpl vpl;
+ int output_port;
+ int datawidth;
};
struct imx_ldb_data {
void __iomem *base;
int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di);
unsigned ipu_mask;
+ int have_mux;
};
struct imx_ldb {
@@ -102,16 +109,11 @@ static const int of_get_data_mapping(struct device_node *np)
return -EINVAL;
}
-static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomode *mode,
+ int di)
{
- struct imx_ldb_channel *imx_ldb_ch = container_of(output, struct imx_ldb_channel, output);
struct imx_ldb *ldb = imx_ldb_ch->ldb;
- if (PICOS2KHZ(mode->pixclock) > 85000) {
- dev_warn(ldb->dev,
- "%s: mode exceeds 85 MHz pixel clock\n", __func__);
- }
-
ldb->soc_data->prepare(imx_ldb_ch, di);
/* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
@@ -141,7 +143,20 @@ static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode,
writel(ldb->ldb_ctrl, ldb->base);
- return 0;
+ return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+ VPL_PREPARE, NULL);
+}
+
+static int imx_ldb_enable(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+ return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+ VPL_ENABLE, NULL);
+}
+
+static int imx_ldb_disable(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+ return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+ VPL_DISABLE, NULL);
}
static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
@@ -226,6 +241,7 @@ static struct imx_ldb_data imx_ldb_data_imx6q = {
.base = (void *)MX6_IOMUXC_BASE_ADDR + 0x8,
.prepare = imx6q_ldb_prepare,
.ipu_mask = 0xf,
+ .have_mux = 1,
};
static struct imx_ldb_data imx_ldb_data_imx53 = {
@@ -234,9 +250,42 @@ static struct imx_ldb_data imx_ldb_data_imx53 = {
.ipu_mask = 0x3,
};
-static struct ipu_output_ops imx_ldb_ops = {
- .prepare = imx_ldb_prepare,
-};
+static int imx_ldb_ioctl(struct vpl *vpl, unsigned int port,
+ unsigned int cmd, void *data)
+{
+ struct imx_ldb_channel *imx_ldb_ch = container_of(vpl,
+ struct imx_ldb_channel, vpl);
+ int ret;
+ struct ipu_di_mode *mode;
+
+ switch (cmd) {
+ case VPL_ENABLE:
+ ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+ if (ret)
+ return ret;
+ return imx_ldb_enable(imx_ldb_ch, port);
+ case VPL_DISABLE:
+ ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+ if (ret)
+ return ret;
+ return imx_ldb_disable(imx_ldb_ch, port);
+ case VPL_PREPARE:
+ ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+ if (ret)
+ return ret;
+ return imx_ldb_prepare(imx_ldb_ch, data, port);
+ case IMX_IPU_VPL_DI_MODE:
+ mode = data;
+
+ mode->di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+ mode->interface_pix_fmt = (imx_ldb_ch->datawidth == 24) ?
+ V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
+
+ return 0;
+ default:
+ return vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+ }
+}
static int imx_ldb_probe(struct device_d *dev)
{
@@ -245,7 +294,6 @@ static int imx_ldb_probe(struct device_d *dev)
struct imx_ldb *imx_ldb;
int ret, i;
int dual = 0;
- int datawidth;
int mapping;
const struct imx_ldb_data *devtype;
@@ -259,6 +307,8 @@ static int imx_ldb_probe(struct device_d *dev)
for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel;
+ struct device_node *port;
+ struct device_node *endpoint;
ret = of_property_read_u32(child, "reg", &i);
if (ret || i < 0 || i > 1)
@@ -275,17 +325,37 @@ static int imx_ldb_probe(struct device_d *dev)
channel = &imx_ldb->channel[i];
channel->ldb = imx_ldb;
channel->chno = i;
+ channel->output_port = imx_ldb->soc_data->have_mux ? 4 : 1;
+
+ /* The output port is port@4 with mux or port@1 without mux */
+ port = of_graph_get_port_by_id(child, channel->output_port);
+ if (!port) {
+ dev_warn(dev, "No port found for %s\n", child->full_name);
+ continue;
+ }
- ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
+ endpoint = of_get_child_by_name(port, "endpoint");
+ if (!endpoint) {
+ dev_warn(dev, "No endpoint found on %s\n", port->full_name);
+ continue;
+ }
+
+ channel->vpl.node = child;
+ channel->vpl.ioctl = &imx_ldb_ioctl;
+ ret = vpl_register(&channel->vpl);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(child, "fsl,data-width", &channel->datawidth);
if (ret)
- datawidth = 0;
- else if (datawidth != 18 && datawidth != 24)
+ channel->datawidth = 0;
+ else if (channel->datawidth != 18 && channel->datawidth != 24)
return -EINVAL;
mapping = of_get_data_mapping(child);
switch (mapping) {
case LVDS_BIT_MAP_SPWG:
- if (datawidth == 24) {
+ if (channel->datawidth == 24) {
if (i == 0 || dual)
imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
if (i == 1 || dual)
@@ -293,7 +363,7 @@ static int imx_ldb_probe(struct device_d *dev)
}
break;
case LVDS_BIT_MAP_JEIDA:
- if (datawidth == 18) {
+ if (channel->datawidth == 18) {
dev_err(dev, "JEIDA standard only supported in 24 bit\n");
return -EINVAL;
}
@@ -306,16 +376,6 @@ static int imx_ldb_probe(struct device_d *dev)
dev_err(dev, "data mapping not specified or invalid\n");
return -EINVAL;
}
-
- channel->output.ops = &imx_ldb_ops;
- channel->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
- channel->output.out_pixel_fmt = (datawidth == 24) ?
- V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
- channel->output.modes = of_get_display_timings(child);
- channel->output.name = asprintf("ldb-%d", i);
- channel->output.ipu_mask = devtype->ipu_mask;
-
- ipu_register_output(&channel->output);
}
return 0;
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
index c032621..74c4dba 100644
--- a/drivers/video/imx-ipu-v3/ipufb.c
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -19,6 +19,7 @@
#include <malloc.h>
#include <errno.h>
#include <init.h>
+#include <of_graph.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm-generic/div64.h>
@@ -62,8 +63,9 @@ struct ipufb_info {
struct list_head list;
char *name;
int id;
+ int dino;
- struct ipu_output *output;
+ struct vpl vpl;
};
static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
@@ -73,23 +75,6 @@ static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
return chan << bf->offset;
}
-static LIST_HEAD(ipu_outputs);
-static LIST_HEAD(ipu_fbs);
-
-int ipu_register_output(struct ipu_output *ouput)
-{
- list_add_tail(&ouput->list, &ipu_outputs);
-
- return 0;
-}
-
-static int ipu_register_fb(struct ipufb_info *ipufb)
-{
- list_add_tail(&ipufb->list, &ipu_fbs);
-
- return 0;
-}
-
int ipu_crtc_mode_set(struct ipufb_info *fbi,
struct fb_videomode *mode,
int x, int y)
@@ -97,14 +82,17 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
struct fb_info *info = &fbi->info;
int ret;
struct ipu_di_signal_cfg sig_cfg = {};
- u32 out_pixel_fmt;
+ struct ipu_di_mode di_mode = {};
+ u32 interface_pix_fmt;
dev_info(fbi->dev, "%s: mode->xres: %d\n", __func__,
mode->xres);
dev_info(fbi->dev, "%s: mode->yres: %d\n", __func__,
mode->yres);
- out_pixel_fmt = fbi->output->out_pixel_fmt;
+ vpl_ioctl(&fbi->vpl, 2 + fbi->dino, IMX_IPU_VPL_DI_MODE, &di_mode);
+ interface_pix_fmt = di_mode.interface_pix_fmt ?
+ di_mode.interface_pix_fmt : fbi->interface_pix_fmt;
if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
sig_cfg.Hsync_pol = 1;
@@ -123,7 +111,7 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
sig_cfg.v_sync_width = mode->vsync_len;
sig_cfg.v_end_width = mode->lower_margin;
sig_cfg.pixelclock = PICOS2KHZ(mode->pixclock) * 1000UL;
- sig_cfg.clkflags = fbi->output->di_clkflags;
+ sig_cfg.clkflags = di_mode.di_clkflags;
sig_cfg.v_to_h_sync = 0;
@@ -131,7 +119,7 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
sig_cfg.vsync_pin = 3;
ret = ipu_dc_init_sync(fbi->dc, fbi->di, sig_cfg.interlaced,
- out_pixel_fmt, mode->xres);
+ interface_pix_fmt, mode->xres);
if (ret) {
dev_err(fbi->dev,
"initializing display controller failed with %d\n",
@@ -170,31 +158,25 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
static void ipufb_enable_controller(struct fb_info *info)
{
struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
- struct ipu_output *output = fbi->output;
- if (output->ops->prepare)
- output->ops->prepare(output, info->mode, fbi->id);
+ vpl_ioctl_prepare(&fbi->vpl, 2 + fbi->dino, info->mode);
ipu_crtc_mode_set(fbi, info->mode, 0, 0);
- if (output->ops->enable)
- output->ops->enable(output, info->mode, fbi->id);
+ vpl_ioctl_enable(&fbi->vpl, 2 + fbi->dino);
}
static void ipufb_disable_controller(struct fb_info *info)
{
struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
- struct ipu_output *output = fbi->output;
- if (output->ops->disable)
- output->ops->disable(output);
+ vpl_ioctl_disable(&fbi->vpl, 2 + fbi->dino);
ipu_plane_disable(fbi->plane[0]);
ipu_dc_disable_channel(fbi->dc);
ipu_di_disable(fbi->di);
- if (output->ops->unprepare)
- output->ops->unprepare(output);
+ vpl_ioctl_unprepare(&fbi->vpl, 2 + fbi->dino);
}
static int ipufb_activate_var(struct fb_info *info)
@@ -207,7 +189,7 @@ static int ipufb_activate_var(struct fb_info *info)
if (!fbi->info.screen_base)
return -ENOMEM;
- memset(fbi->info.screen_base, 0, info->line_length * info->yres);
+ memset(fbi->info.screen_base, 0x0, info->line_length * info->yres);
return 0;
}
@@ -218,56 +200,6 @@ static struct fb_ops ipufb_ops = {
.fb_activate_var = ipufb_activate_var,
};
-static struct ipufb_info *ipu_output_find_di(struct ipu_output *output)
-{
- struct ipufb_info *ipufb;
-
- list_for_each_entry(ipufb, &ipu_fbs, list) {
- if (!(output->ipu_mask & (1 << ipufb->id)))
- continue;
- if (ipufb->output)
- continue;
-
- return ipufb;
- }
-
- return NULL;
-}
-
-static int ipu_init(void)
-{
- struct ipu_output *output;
- struct ipufb_info *ipufb;
- int ret;
-
- list_for_each_entry(output, &ipu_outputs, list) {
- pr_info("found output: %s\n", output->name);
- ipufb = ipu_output_find_di(output);
- if (!ipufb) {
- pr_info("no di found for output %s\n", output->name);
- continue;
- }
- pr_info("using di %s for output %s\n", ipufb->name, output->name);
-
- ipufb->output = output;
-
- ipufb->info.edid_i2c_adapter = output->edid_i2c_adapter;
- if (output->modes) {
- ipufb->info.modes.modes = output->modes->modes;
- ipufb->info.modes.num_modes = output->modes->num_modes;
- }
-
- ret = register_framebuffer(&ipufb->info);
- if (ret < 0) {
- dev_err(ipufb->dev, "failed to register framebuffer\n");
- return ret;
- }
- }
-
- return 0;
-}
-late_initcall(ipu_init);
-
static int ipu_get_resources(struct ipufb_info *fbi,
struct ipu_client_platformdata *pdata)
{
@@ -310,6 +242,8 @@ static int ipufb_probe(struct device_d *dev)
int ret, ipuid;
struct ipu_client_platformdata *pdata = dev->platform_data;
struct ipu_rgb *ipu_rgb;
+ struct device_node *node;
+ const char *fmt;
fbi = xzalloc(sizeof(*fbi));
info = &fbi->info;
@@ -317,6 +251,7 @@ static int ipufb_probe(struct device_d *dev)
ipuid = of_alias_get_id(dev->parent->device_node, "ipu");
fbi->name = asprintf("ipu%d-di%d", ipuid + 1, pdata->di);
fbi->id = ipuid * 2 + pdata->di;
+ fbi->dino = pdata->di;
fbi->dev = dev;
info->priv = fbi;
@@ -336,7 +271,38 @@ static int ipufb_probe(struct device_d *dev)
if (ret)
return ret;
- ret = ipu_register_fb(fbi);
+ node = of_graph_get_port_by_id(dev->parent->device_node, 2 + pdata->di);
+ if (node && of_graph_port_is_available(node)) {
+ dev_info(fbi->dev, "register vpl for %s\n", dev->parent->device_node->full_name);
+
+ fbi->vpl.node = dev->parent->device_node;
+ ret = vpl_register(&fbi->vpl);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_string(node, "interface-pix-fmt", &fmt);
+ if (!ret) {
+ if (!strcmp(fmt, "rgb24"))
+ fbi->interface_pix_fmt = V4L2_PIX_FMT_RGB24;
+ else if (!strcmp(fmt, "rgb565"))
+ fbi->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
+ else if (!strcmp(fmt, "bgr666"))
+ fbi->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
+ else if (!strcmp(fmt, "lvds666"))
+ fbi->interface_pix_fmt =
+ v4l2_fourcc('L', 'V', 'D', '6');
+ }
+
+ ret = vpl_ioctl(&fbi->vpl, 2 + fbi->dino, VPL_GET_VIDEOMODES, &info->modes);
+ if (ret)
+ return ret;
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_err(fbi->dev, "failed to register framebuffer\n");
+ return ret;
+ }
+ }
return ret;
}
@@ -350,4 +316,9 @@ static struct driver_d ipufb_driver = {
.probe = ipufb_probe,
.remove = ipufb_remove,
};
-device_platform_driver(ipufb_driver);
+
+static int ipufb_register(void)
+{
+ return platform_driver_register(&ipufb_driver);
+}
+late_initcall(ipufb_register);
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2015-07-09 7:24 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-09 7:24 Video support for EfikaSB Sascha Hauer
2015-07-09 7:24 ` [PATCH 01/13] of: base: implement of_get_next_child Sascha Hauer
2015-07-09 7:24 ` [PATCH 02/13] of: import of_graph functions Sascha Hauer
2015-07-09 7:24 ` [PATCH 03/13] of_graph: add of_graph_port_is_available Sascha Hauer
2015-07-09 7:24 ` [PATCH 04/13] ARM: i.MX51 Efikasb: Disable backlight earlier Sascha Hauer
2015-07-09 7:24 ` [PATCH 05/13] ARM: i.MX51 Efikasb: make more space for barebox Sascha Hauer
2015-07-09 7:24 ` [PATCH 06/13] ARM: i.MX51 Efikasb: update device tree Sascha Hauer
2015-07-09 7:24 ` [PATCH 07/13] video: Add Video Pipeline (VPL) support Sascha Hauer
2015-07-09 7:24 ` [PATCH 08/13] video: Add MTL017 LVDS encoder support Sascha Hauer
2015-07-09 7:24 ` [PATCH 09/13] video: Add missing prototype for display_timings_release Sascha Hauer
2015-07-09 7:24 ` [PATCH 10/13] video: ipuv3: remove unused variable Sascha Hauer
2015-07-09 7:24 ` Sascha Hauer [this message]
2015-07-09 7:24 ` [PATCH 12/13] video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description Sascha Hauer
2015-07-09 7:24 ` [PATCH 13/13] video: Add simple-panel support Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1436426657-5266-12-git-send-email-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox