summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2019-11-12 13:56:45 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:58:23 +0800
commita1ab21d2fc621a8b6ee4691cbc9c909b8ce7d383 (patch)
tree2d5643255c2ccf70cf0c9d3d85a62c01256fbd54
parent15952eb997ea126b615878f9ceae359597f4fdff (diff)
gpu: imx: dpu: Add pixel combiner support
This patch adds pixel combiner support in the DPU core driver. Users may get and enable/disable/control a pixel combiner instant via tcon functions and may tell if it is needed in a specific usecase via the dpu_get_syncmode_min_prate() and dpu_get_singlemode_max_width() helpers. Signed-off-by: Liu Ying <victor.liu@nxp.com>
-rw-r--r--drivers/gpu/imx/dpu/dpu-common.c56
-rw-r--r--drivers/gpu/imx/dpu/dpu-prv.h4
-rw-r--r--drivers/gpu/imx/dpu/dpu-tcon.c38
-rw-r--r--include/video/dpu.h6
4 files changed, 101 insertions, 3 deletions
diff --git a/drivers/gpu/imx/dpu/dpu-common.c b/drivers/gpu/imx/dpu/dpu-common.c
index 7c2a3b8f6cd5..deea323d4359 100644
--- a/drivers/gpu/imx/dpu/dpu-common.c
+++ b/drivers/gpu/imx/dpu/dpu-common.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <video/dpu.h>
+#include <video/imx8-pc.h>
#include <video/imx8-prefetch.h>
#include "dpu-prv.h"
@@ -235,7 +236,7 @@ static const struct cm_reg_ofs _cm_reg_ofs = {
static const unsigned long unused_irq[] = {0x00000000, 0xfffe0008};
-static const struct dpu_data dpu_data = {
+static const struct dpu_data dpu_data_qxp = {
.cm_ofs = 0x0,
.cfs = &_cfs,
.decs = &_decs,
@@ -253,21 +254,57 @@ static const struct dpu_data dpu_data = {
.unused_irq = unused_irq,
.plane_src_mask = DPU_PLANE_SRC_FL0_ID | DPU_PLANE_SRC_FW2_ID |
DPU_PLANE_SRC_FD0_ID | DPU_PLANE_SRC_FD1_ID,
+ .syncmode_min_prate = UINT_MAX, /* pc is unused */
+ .singlemode_max_width = UINT_MAX, /* pc is unused */
+};
+
+static const struct dpu_data dpu_data_qm = {
+ .cm_ofs = 0x0,
+ .cfs = &_cfs,
+ .decs = &_decs,
+ .eds = &_eds,
+ .fds = &_fds,
+ .fes = &_fes,
+ .fgs = &_fgs,
+ .fls = &_fls,
+ .fws = &_fws,
+ .hss = &_hss,
+ .lbs = &_lbs,
+ .tcons = &_tcons,
+ .vss = &_vss,
+ .cm_reg_ofs = &_cm_reg_ofs,
+ .unused_irq = unused_irq,
+ .plane_src_mask = DPU_PLANE_SRC_FL0_ID | DPU_PLANE_SRC_FW2_ID |
+ DPU_PLANE_SRC_FD0_ID | DPU_PLANE_SRC_FD1_ID,
+ .syncmode_min_prate = 300000,
+ .singlemode_max_width = 1920,
};
static const struct of_device_id dpu_dt_ids[] = {
{
.compatible = "fsl,imx8qxp-dpu",
- .data = &dpu_data,
+ .data = &dpu_data_qxp,
}, {
.compatible = "fsl,imx8qm-dpu",
- .data = &dpu_data,
+ .data = &dpu_data_qm,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, dpu_dt_ids);
+unsigned int dpu_get_syncmode_min_prate(struct dpu_soc *dpu)
+{
+ return dpu->data->syncmode_min_prate;
+}
+EXPORT_SYMBOL_GPL(dpu_get_syncmode_min_prate);
+
+unsigned int dpu_get_singlemode_max_width(struct dpu_soc *dpu)
+{
+ return dpu->data->singlemode_max_width;
+}
+EXPORT_SYMBOL_GPL(dpu_get_singlemode_max_width);
+
unsigned int dpu_get_master_stream_id(struct dpu_soc *dpu)
{
return dpu->data->master_stream_id;
@@ -720,8 +757,11 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
const struct dpu_unit *fds = data->fds;
const struct dpu_unit *fls = data->fls;
const struct dpu_unit *fws = data->fws;
+ const struct dpu_unit *tcons = data->tcons;
struct dpu_fetchunit *fu;
struct dprc *dprc;
+ struct dpu_tcon *tcon;
+ struct pc *pc;
int i;
DPU_UNITS_INIT(cf);
@@ -770,6 +810,16 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
dpu_fw_put(fu);
}
+ pc = pc_lookup_by_phandle(dpu->dev, "fsl,pixel-combiner");
+ if (!pc)
+ return -EPROBE_DEFER;
+
+ for (i = 0; i < tcons->num; i++) {
+ tcon = dpu_tcon_get(dpu, i);
+ tcon_get_pc(tcon, pc);
+ dpu_tcon_put(tcon);
+ }
+
return 0;
}
diff --git a/drivers/gpu/imx/dpu/dpu-prv.h b/drivers/gpu/imx/dpu/dpu-prv.h
index dcbfcd4e00b5..9bdd71f613b6 100644
--- a/drivers/gpu/imx/dpu/dpu-prv.h
+++ b/drivers/gpu/imx/dpu/dpu-prv.h
@@ -192,6 +192,8 @@ struct dpu_data {
const struct cm_reg_ofs *cm_reg_ofs;
const unsigned long *unused_irq;
+ unsigned int syncmode_min_prate; /* need pixel combiner, KHz */
+ unsigned int singlemode_max_width;
unsigned int master_stream_id;
u32 plane_src_mask;
@@ -315,6 +317,8 @@ static inline u32 yuv_color(u8 y, u8 u, u8 v)
return (y << 24) | (u << 16) | (v << 8);
}
+void tcon_get_pc(struct dpu_tcon *tcon, void *data);
+
static const unsigned int cf_ids[] = {0, 1, 4, 5};
static const unsigned int dec_ids[] = {0, 1};
static const unsigned int ed_ids[] = {0, 1, 4, 5};
diff --git a/drivers/gpu/imx/dpu/dpu-tcon.c b/drivers/gpu/imx/dpu/dpu-tcon.c
index aa5f45115bc2..fe046520b13a 100644
--- a/drivers/gpu/imx/dpu/dpu-tcon.c
+++ b/drivers/gpu/imx/dpu/dpu-tcon.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/types.h>
#include <video/dpu.h>
+#include <video/imx8-pc.h>
#include "dpu-prv.h"
#define SSQCNTS 0
@@ -63,6 +64,7 @@ struct dpu_tcon {
int id;
bool inuse;
struct dpu_soc *dpu;
+ struct pc *pc;
};
static inline u32 dpu_tcon_read(struct dpu_tcon *tcon, unsigned int offset)
@@ -220,6 +222,34 @@ bool tcon_is_slave(struct dpu_tcon *tcon)
}
EXPORT_SYMBOL_GPL(tcon_is_slave);
+void tcon_configure_pc(struct dpu_tcon *tcon, unsigned int di,
+ unsigned int frame_width, u32 mode, u32 format)
+{
+ if (WARN_ON(!tcon || !tcon->pc))
+ return;
+
+ pc_configure(tcon->pc, di, frame_width, mode, format);
+}
+EXPORT_SYMBOL_GPL(tcon_configure_pc);
+
+void tcon_enable_pc(struct dpu_tcon *tcon)
+{
+ if (WARN_ON(!tcon || !tcon->pc))
+ return;
+
+ pc_enable(tcon->pc);
+}
+EXPORT_SYMBOL_GPL(tcon_enable_pc);
+
+void tcon_disable_pc(struct dpu_tcon *tcon)
+{
+ if (WARN_ON(!tcon || !tcon->pc))
+ return;
+
+ pc_disable(tcon->pc);
+}
+EXPORT_SYMBOL_GPL(tcon_disable_pc);
+
struct dpu_tcon *dpu_tcon_get(struct dpu_soc *dpu, int id)
{
struct dpu_tcon *tcon;
@@ -289,3 +319,11 @@ int dpu_tcon_init(struct dpu_soc *dpu, unsigned int id,
return 0;
}
+
+void tcon_get_pc(struct dpu_tcon *tcon, void *data)
+{
+ if (WARN_ON(!tcon))
+ return;
+
+ tcon->pc = data;
+}
diff --git a/include/video/dpu.h b/include/video/dpu.h
index ed9b65cacde7..1cc5c8c5ccaf 100644
--- a/include/video/dpu.h
+++ b/include/video/dpu.h
@@ -557,6 +557,10 @@ void tcon_cfg_videomode(struct dpu_tcon *tcon,
struct drm_display_mode *m, bool side_by_side);
bool tcon_is_master(struct dpu_tcon *tcon);
bool tcon_is_slave(struct dpu_tcon *tcon);
+void tcon_configure_pc(struct dpu_tcon *tcon, unsigned int di,
+ unsigned int frame_width, u32 mode, u32 format);
+void tcon_enable_pc(struct dpu_tcon *tcon);
+void tcon_disable_pc(struct dpu_tcon *tcon);
struct dpu_tcon *dpu_tcon_get(struct dpu_soc *dpu, int id);
void dpu_tcon_put(struct dpu_tcon *tcon);
struct dpu_tcon *dpu_aux_tcon_peek(struct dpu_tcon *tcon);
@@ -587,6 +591,8 @@ struct dpu_fetchunit *fetchdecode_get_fetcheco(struct dpu_fetchunit *fu);
struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchunit *fu);
struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchunit *fu);
+unsigned int dpu_get_syncmode_min_prate(struct dpu_soc *dpu);
+unsigned int dpu_get_singlemode_max_width(struct dpu_soc *dpu);
unsigned int dpu_get_master_stream_id(struct dpu_soc *dpu);
bool dpu_vproc_has_fetcheco_cap(u32 cap_mask);