aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBibby Hsieh <bibby.hsieh@mediatek.com>2016-07-27 22:22:55 -0400
committerPhilipp Zabel <p.zabel@pengutronix.de>2016-08-11 04:52:23 -0400
commit7216436420414144646f5d8343d061355fd23483 (patch)
tree2c165aea9b4c7272e46114182f2d85412acd643d
parent2f3f4dda747c0619594d13996e65598ab675c60c (diff)
drm/mediatek: set mt8173 dithering function
Some panels only accept bpc (bit per color) 6-bit. But, the default bpc in mt8173 display data path is 8-bit. If we didn't enable dithering function to convert bpc, display cannot show the smooth grayscale image. In mt8173, the dithering function in OD (OverDrive) and GAMMA module, we have to config them with connector->display_mode.bpc when CRTC initial. 1. Clear the default value at *_DITHER_5 and *_DITHER_7 register. 2. Calculate the LSB_ERR_SHIFT bits and ADD_LSHIFT bits two values. i.e. Input bpc of OD is 10 bits, we assume the bpc of panel is 6-bit, so, we need to set 4-bit to LSB_ERR_SHIFT and ADD_LSHIFT bits respectively. 3. Then, set the OD or GAMMA to dithering mode depends on path-1 or path-2. Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_rdma.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c21
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c72
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h8
6 files changed, 89 insertions, 20 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 8f62671fcfbf..019b7ca392d7 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -103,7 +103,8 @@ static void mtk_ovl_stop(struct mtk_ddp_comp *comp)
103} 103}
104 104
105static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w, 105static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,
106 unsigned int h, unsigned int vrefresh) 106 unsigned int h, unsigned int vrefresh,
107 unsigned int bpc)
107{ 108{
108 if (w != 0 && h != 0) 109 if (w != 0 && h != 0)
109 writel_relaxed(h << 16 | w, comp->regs + DISP_REG_OVL_ROI_SIZE); 110 writel_relaxed(h << 16 | w, comp->regs + DISP_REG_OVL_ROI_SIZE);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 5fb80cbe4c5b..0df05f95b916 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -106,7 +106,8 @@ static void mtk_rdma_stop(struct mtk_ddp_comp *comp)
106} 106}
107 107
108static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, 108static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
109 unsigned int height, unsigned int vrefresh) 109 unsigned int height, unsigned int vrefresh,
110 unsigned int bpc)
110{ 111{
111 unsigned int threshold; 112 unsigned int threshold;
112 unsigned int reg; 113 unsigned int reg;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index e3ac2802e024..58725d34d411 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -222,7 +222,9 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
222static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) 222static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
223{ 223{
224 struct drm_crtc *crtc = &mtk_crtc->base; 224 struct drm_crtc *crtc = &mtk_crtc->base;
225 unsigned int width, height, vrefresh; 225 struct drm_connector *connector;
226 struct drm_encoder *encoder;
227 unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
226 int ret; 228 int ret;
227 int i; 229 int i;
228 230
@@ -234,6 +236,19 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
234 height = crtc->state->adjusted_mode.vdisplay; 236 height = crtc->state->adjusted_mode.vdisplay;
235 vrefresh = crtc->state->adjusted_mode.vrefresh; 237 vrefresh = crtc->state->adjusted_mode.vrefresh;
236 238
239 drm_for_each_encoder(encoder, crtc->dev) {
240 if (encoder->crtc != crtc)
241 continue;
242
243 drm_for_each_connector(connector, crtc->dev) {
244 if (connector->encoder != encoder)
245 continue;
246 if (connector->display_info.bpc != 0 &&
247 bpc > connector->display_info.bpc)
248 bpc = connector->display_info.bpc;
249 }
250 }
251
237 ret = pm_runtime_get_sync(crtc->dev->dev); 252 ret = pm_runtime_get_sync(crtc->dev->dev);
238 if (ret < 0) { 253 if (ret < 0) {
239 DRM_ERROR("Failed to enable power domain: %d\n", ret); 254 DRM_ERROR("Failed to enable power domain: %d\n", ret);
@@ -266,7 +281,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
266 for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { 281 for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
267 struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i]; 282 struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
268 283
269 mtk_ddp_comp_config(comp, width, height, vrefresh); 284 mtk_ddp_comp_config(comp, width, height, vrefresh, bpc);
270 mtk_ddp_comp_start(comp); 285 mtk_ddp_comp_start(comp);
271 } 286 }
272 287
@@ -468,7 +483,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
468 if (state->pending_config) { 483 if (state->pending_config) {
469 mtk_ddp_comp_config(ovl, state->pending_width, 484 mtk_ddp_comp_config(ovl, state->pending_width,
470 state->pending_height, 485 state->pending_height,
471 state->pending_vrefresh); 486 state->pending_vrefresh, 0);
472 487
473 state->pending_config = false; 488 state->pending_config = false;
474 } 489 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
index d332564065e3..33f6ab65eb59 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
@@ -20,6 +20,8 @@
20 20
21#define OVL_LAYER_NR 4 21#define OVL_LAYER_NR 4
22#define MTK_LUT_SIZE 512 22#define MTK_LUT_SIZE 512
23#define MTK_MAX_BPC 10
24#define MTK_MIN_BPC 3
23 25
24int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe); 26int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe);
25void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe); 27void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 42cd587d6b9b..df33b3ca6ffd 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -31,6 +31,10 @@
31#define DISP_OD_INTSTA 0x000c 31#define DISP_OD_INTSTA 0x000c
32#define DISP_OD_CFG 0x0020 32#define DISP_OD_CFG 0x0020
33#define DISP_OD_SIZE 0x0030 33#define DISP_OD_SIZE 0x0030
34#define DISP_DITHER_5 0x0114
35#define DISP_DITHER_7 0x011c
36#define DISP_DITHER_15 0x013c
37#define DISP_DITHER_16 0x0140
34 38
35#define DISP_REG_UFO_START 0x0000 39#define DISP_REG_UFO_START 0x0000
36 40
@@ -49,20 +53,59 @@
49 53
50#define LUT_10BIT_MASK 0x03ff 54#define LUT_10BIT_MASK 0x03ff
51 55
52#define OD_RELAY_MODE BIT(0) 56#define COLOR_BYPASS_ALL BIT(7)
57#define COLOR_SEQ_SEL BIT(13)
53 58
54#define UFO_BYPASS BIT(2) 59#define OD_RELAYMODE BIT(0)
55 60
56#define COLOR_BYPASS_ALL BIT(7) 61#define UFO_BYPASS BIT(2)
57#define COLOR_SEQ_SEL BIT(13)
58 62
59#define AAL_EN BIT(0) 63#define AAL_EN BIT(0)
60 64
61#define GAMMA_EN BIT(0) 65#define GAMMA_EN BIT(0)
62#define GAMMA_LUT_EN BIT(1) 66#define GAMMA_LUT_EN BIT(1)
67
68#define DISP_DITHERING BIT(2)
69#define DITHER_LSB_ERR_SHIFT_R(x) (((x) & 0x7) << 28)
70#define DITHER_OVFLW_BIT_R(x) (((x) & 0x7) << 24)
71#define DITHER_ADD_LSHIFT_R(x) (((x) & 0x7) << 20)
72#define DITHER_ADD_RSHIFT_R(x) (((x) & 0x7) << 16)
73#define DITHER_NEW_BIT_MODE BIT(0)
74#define DITHER_LSB_ERR_SHIFT_B(x) (((x) & 0x7) << 28)
75#define DITHER_OVFLW_BIT_B(x) (((x) & 0x7) << 24)
76#define DITHER_ADD_LSHIFT_B(x) (((x) & 0x7) << 20)
77#define DITHER_ADD_RSHIFT_B(x) (((x) & 0x7) << 16)
78#define DITHER_LSB_ERR_SHIFT_G(x) (((x) & 0x7) << 12)
79#define DITHER_OVFLW_BIT_G(x) (((x) & 0x7) << 8)
80#define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4)
81#define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0)
82
83void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
84 unsigned int CFG)
85{
86 /* If bpc equal to 0, the dithering function didn't be enabled */
87 if (bpc == 0)
88 return;
89
90 if (bpc >= MTK_MIN_BPC) {
91 writel(0, comp->regs + DISP_DITHER_5);
92 writel(0, comp->regs + DISP_DITHER_7);
93 writel(DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
94 DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
95 DITHER_NEW_BIT_MODE,
96 comp->regs + DISP_DITHER_15);
97 writel(DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
98 DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
99 DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
100 DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
101 comp->regs + DISP_DITHER_16);
102 writel(DISP_DITHERING, comp->regs + CFG);
103 }
104}
63 105
64static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w, 106static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
65 unsigned int h, unsigned int vrefresh) 107 unsigned int h, unsigned int vrefresh,
108 unsigned int bpc)
66{ 109{
67 writel(w, comp->regs + DISP_COLOR_WIDTH); 110 writel(w, comp->regs + DISP_COLOR_WIDTH);
68 writel(h, comp->regs + DISP_COLOR_HEIGHT); 111 writel(h, comp->regs + DISP_COLOR_HEIGHT);
@@ -76,14 +119,16 @@ static void mtk_color_start(struct mtk_ddp_comp *comp)
76} 119}
77 120
78static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, 121static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
79 unsigned int h, unsigned int vrefresh) 122 unsigned int h, unsigned int vrefresh,
123 unsigned int bpc)
80{ 124{
81 writel(w << 16 | h, comp->regs + DISP_OD_SIZE); 125 writel(w << 16 | h, comp->regs + DISP_OD_SIZE);
126 writel(OD_RELAYMODE, comp->regs + OD_RELAYMODE);
127 mtk_dither_set(comp, bpc, DISP_OD_CFG);
82} 128}
83 129
84static void mtk_od_start(struct mtk_ddp_comp *comp) 130static void mtk_od_start(struct mtk_ddp_comp *comp)
85{ 131{
86 writel(OD_RELAY_MODE, comp->regs + DISP_OD_CFG);
87 writel(1, comp->regs + DISP_OD_EN); 132 writel(1, comp->regs + DISP_OD_EN);
88} 133}
89 134
@@ -93,7 +138,8 @@ static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
93} 138}
94 139
95static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w, 140static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w,
96 unsigned int h, unsigned int vrefresh) 141 unsigned int h, unsigned int vrefresh,
142 unsigned int bpc)
97{ 143{
98 writel(h << 16 | w, comp->regs + DISP_AAL_SIZE); 144 writel(h << 16 | w, comp->regs + DISP_AAL_SIZE);
99} 145}
@@ -109,9 +155,11 @@ static void mtk_aal_stop(struct mtk_ddp_comp *comp)
109} 155}
110 156
111static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w, 157static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w,
112 unsigned int h, unsigned int vrefresh) 158 unsigned int h, unsigned int vrefresh,
159 unsigned int bpc)
113{ 160{
114 writel(h << 16 | w, comp->regs + DISP_GAMMA_SIZE); 161 writel(h << 16 | w, comp->regs + DISP_GAMMA_SIZE);
162 mtk_dither_set(comp, bpc, DISP_GAMMA_CFG);
115} 163}
116 164
117static void mtk_gamma_start(struct mtk_ddp_comp *comp) 165static void mtk_gamma_start(struct mtk_ddp_comp *comp)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index f4b7e0ae7379..22a33ee451c4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -65,7 +65,7 @@ struct mtk_ddp_comp;
65 65
66struct mtk_ddp_comp_funcs { 66struct mtk_ddp_comp_funcs {
67 void (*config)(struct mtk_ddp_comp *comp, unsigned int w, 67 void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
68 unsigned int h, unsigned int vrefresh); 68 unsigned int h, unsigned int vrefresh, unsigned int bpc);
69 void (*start)(struct mtk_ddp_comp *comp); 69 void (*start)(struct mtk_ddp_comp *comp);
70 void (*stop)(struct mtk_ddp_comp *comp); 70 void (*stop)(struct mtk_ddp_comp *comp);
71 void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc); 71 void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc);
@@ -89,10 +89,10 @@ struct mtk_ddp_comp {
89 89
90static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp, 90static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
91 unsigned int w, unsigned int h, 91 unsigned int w, unsigned int h,
92 unsigned int vrefresh) 92 unsigned int vrefresh, unsigned int bpc)
93{ 93{
94 if (comp->funcs && comp->funcs->config) 94 if (comp->funcs && comp->funcs->config)
95 comp->funcs->config(comp, w, h, vrefresh); 95 comp->funcs->config(comp, w, h, vrefresh, bpc);
96} 96}
97 97
98static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp) 98static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp)
@@ -156,5 +156,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node,
156 const struct mtk_ddp_comp_funcs *funcs); 156 const struct mtk_ddp_comp_funcs *funcs);
157int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp); 157int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp);
158void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp); 158void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp);
159void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
160 unsigned int CFG);
159 161
160#endif /* MTK_DRM_DDP_COMP_H */ 162#endif /* MTK_DRM_DDP_COMP_H */