aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-09-27 21:23:15 -0400
committerDave Airlie <airlied@redhat.com>2016-09-27 21:23:15 -0400
commita4a7fbb4015d8f5726ff9c97a97f7ffbdc3f271e (patch)
tree9638e02f1d641ac42425b8897e1e2891a35cb616
parent378db830c3cc5c05e2c176274b0d2fcee0b133f3 (diff)
parentf0188ef8301ccbb128bbfd10751a9aeca8c9172e (diff)
Merge tag 'sunxi-drm-fixes-for-4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into drm-next
Allwinner sun4i DRM fixes for 4.9 A few fixes for the sun4i drm driver that range, including some fixes that might prevent multiple planes from working depending on the sequence where they are enabled. * tag 'sunxi-drm-fixes-for-4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux: drm/sun4i: Fix the high buffer address mask drm/sun4i: tv: Check mode pointer drm/sun4i: Fix formats usable by the primary plane drm/sun4i: dotclock: Round to closest clock rate drm/sun4i: Fix sparse warnings drm/sun4i: dotclock: Allow divider = 127 drm/sun4i: dotclock: Fix clock rate read back calcation drm/sun4i: backend: remove redundant dev_err call in sun4i_backend_bind()
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c13
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.h4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_dotclock.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c56
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tv.c46
5 files changed, 79 insertions, 47 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 91a702225ded..32c0584e3c35 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -83,8 +83,13 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
83} 83}
84EXPORT_SYMBOL(sun4i_backend_layer_enable); 84EXPORT_SYMBOL(sun4i_backend_layer_enable);
85 85
86static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) 86static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
87 u32 format, u32 *mode)
87{ 88{
89 if ((plane->type == DRM_PLANE_TYPE_PRIMARY) &&
90 (format == DRM_FORMAT_ARGB8888))
91 format = DRM_FORMAT_XRGB8888;
92
88 switch (format) { 93 switch (format) {
89 case DRM_FORMAT_ARGB8888: 94 case DRM_FORMAT_ARGB8888:
90 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; 95 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
@@ -164,7 +169,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
164 DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", 169 DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
165 interlaced ? "on" : "off"); 170 interlaced ? "on" : "off");
166 171
167 ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val); 172 ret = sun4i_backend_drm_format_to_layer(plane, fb->pixel_format, &val);
168 if (ret) { 173 if (ret) {
169 DRM_DEBUG_DRIVER("Invalid format\n"); 174 DRM_DEBUG_DRIVER("Invalid format\n");
170 return val; 175 return val;
@@ -288,10 +293,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
288 293
289 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 294 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
290 regs = devm_ioremap_resource(dev, res); 295 regs = devm_ioremap_resource(dev, res);
291 if (IS_ERR(regs)) { 296 if (IS_ERR(regs))
292 dev_err(dev, "Couldn't map the backend registers\n");
293 return PTR_ERR(regs); 297 return PTR_ERR(regs);
294 }
295 298
296 backend->regs = devm_regmap_init_mmio(dev, regs, 299 backend->regs = devm_regmap_init_mmio(dev, regs,
297 &sun4i_backend_regmap_config); 300 &sun4i_backend_regmap_config);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index e00718627748..83e63cc702b4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -52,8 +52,8 @@
52#define SUN4I_BACKEND_LAYFB_L32ADD_REG(l) (0x850 + (0x4 * (l))) 52#define SUN4I_BACKEND_LAYFB_L32ADD_REG(l) (0x850 + (0x4 * (l)))
53 53
54#define SUN4I_BACKEND_LAYFB_H4ADD_REG 0x860 54#define SUN4I_BACKEND_LAYFB_H4ADD_REG 0x860
55#define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l) GENMASK(3 + ((l) * 8), 0) 55#define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l) GENMASK(3 + ((l) * 8), (l) * 8)
56#define SUN4I_BACKEND_LAYFB_H4ADD(l, val) ((val) << ((l) * 8)) 56#define SUN4I_BACKEND_LAYFB_H4ADD(l, val) ((val) << ((l) * 8))
57 57
58#define SUN4I_BACKEND_REGBUFFCTL_REG 0x870 58#define SUN4I_BACKEND_REGBUFFCTL_REG 0x870
59#define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS BIT(1) 59#define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS BIT(1)
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 4332da48b1b3..d401156490f3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -62,7 +62,7 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
62 regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val); 62 regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val);
63 63
64 val >>= SUN4I_TCON0_DCLK_DIV_SHIFT; 64 val >>= SUN4I_TCON0_DCLK_DIV_SHIFT;
65 val &= SUN4I_TCON0_DCLK_DIV_WIDTH; 65 val &= (1 << SUN4I_TCON0_DCLK_DIV_WIDTH) - 1;
66 66
67 if (!val) 67 if (!val)
68 val = 1; 68 val = 1;
@@ -77,7 +77,7 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
77 u8 best_div = 1; 77 u8 best_div = 1;
78 int i; 78 int i;
79 79
80 for (i = 6; i < 127; i++) { 80 for (i = 6; i <= 127; i++) {
81 unsigned long ideal = rate * i; 81 unsigned long ideal = rate * i;
82 unsigned long rounded; 82 unsigned long rounded;
83 83
@@ -90,7 +90,8 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
90 goto out; 90 goto out;
91 } 91 }
92 92
93 if ((rounded < ideal) && (rounded > best_parent)) { 93 if (abs(rate - rounded / i) <
94 abs(rate - best_parent / best_div)) {
94 best_parent = rounded; 95 best_parent = rounded;
95 best_div = i; 96 best_div = i;
96 } 97 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 068ab806309b..f0035bf5efea 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -19,7 +19,12 @@
19#include "sun4i_drv.h" 19#include "sun4i_drv.h"
20#include "sun4i_layer.h" 20#include "sun4i_layer.h"
21 21
22#define SUN4I_NUM_LAYERS 2 22struct sun4i_plane_desc {
23 enum drm_plane_type type;
24 u8 pipe;
25 const uint32_t *formats;
26 uint32_t nformats;
27};
23 28
24static int sun4i_backend_layer_atomic_check(struct drm_plane *plane, 29static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
25 struct drm_plane_state *state) 30 struct drm_plane_state *state)
@@ -65,14 +70,35 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
65 .update_plane = drm_atomic_helper_update_plane, 70 .update_plane = drm_atomic_helper_update_plane,
66}; 71};
67 72
68static const uint32_t sun4i_backend_layer_formats[] = { 73static const uint32_t sun4i_backend_layer_formats_primary[] = {
69 DRM_FORMAT_ARGB8888, 74 DRM_FORMAT_ARGB8888,
75 DRM_FORMAT_RGB888,
70 DRM_FORMAT_XRGB8888, 76 DRM_FORMAT_XRGB8888,
77};
78
79static const uint32_t sun4i_backend_layer_formats_overlay[] = {
80 DRM_FORMAT_ARGB8888,
71 DRM_FORMAT_RGB888, 81 DRM_FORMAT_RGB888,
82 DRM_FORMAT_XRGB8888,
83};
84
85static const struct sun4i_plane_desc sun4i_backend_planes[] = {
86 {
87 .type = DRM_PLANE_TYPE_PRIMARY,
88 .pipe = 0,
89 .formats = sun4i_backend_layer_formats_primary,
90 .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary),
91 },
92 {
93 .type = DRM_PLANE_TYPE_OVERLAY,
94 .pipe = 1,
95 .formats = sun4i_backend_layer_formats_overlay,
96 .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay),
97 },
72}; 98};
73 99
74static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, 100static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
75 enum drm_plane_type type) 101 const struct sun4i_plane_desc *plane)
76{ 102{
77 struct sun4i_drv *drv = drm->dev_private; 103 struct sun4i_drv *drv = drm->dev_private;
78 struct sun4i_layer *layer; 104 struct sun4i_layer *layer;
@@ -84,10 +110,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
84 110
85 ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), 111 ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
86 &sun4i_backend_layer_funcs, 112 &sun4i_backend_layer_funcs,
87 sun4i_backend_layer_formats, 113 plane->formats, plane->nformats,
88 ARRAY_SIZE(sun4i_backend_layer_formats), 114 plane->type, NULL);
89 type,
90 NULL);
91 if (ret) { 115 if (ret) {
92 dev_err(drm->dev, "Couldn't initialize layer\n"); 116 dev_err(drm->dev, "Couldn't initialize layer\n");
93 return ERR_PTR(ret); 117 return ERR_PTR(ret);
@@ -97,7 +121,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
97 &sun4i_backend_layer_helper_funcs); 121 &sun4i_backend_layer_helper_funcs);
98 layer->drv = drv; 122 layer->drv = drv;
99 123
100 if (type == DRM_PLANE_TYPE_PRIMARY) 124 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
101 drv->primary = &layer->plane; 125 drv->primary = &layer->plane;
102 126
103 return layer; 127 return layer;
@@ -109,8 +133,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
109 struct sun4i_layer **layers; 133 struct sun4i_layer **layers;
110 int i; 134 int i;
111 135
112 layers = devm_kcalloc(drm->dev, SUN4I_NUM_LAYERS, sizeof(**layers), 136 layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes),
113 GFP_KERNEL); 137 sizeof(**layers), GFP_KERNEL);
114 if (!layers) 138 if (!layers)
115 return ERR_PTR(-ENOMEM); 139 return ERR_PTR(-ENOMEM);
116 140
@@ -135,13 +159,11 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
135 * SoCs that support it, sprites could fill the need for more 159 * SoCs that support it, sprites could fill the need for more
136 * layers. 160 * layers.
137 */ 161 */
138 for (i = 0; i < SUN4I_NUM_LAYERS; i++) { 162 for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
139 enum drm_plane_type type = (i == 0) 163 const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
140 ? DRM_PLANE_TYPE_PRIMARY
141 : DRM_PLANE_TYPE_OVERLAY;
142 struct sun4i_layer *layer = layers[i]; 164 struct sun4i_layer *layer = layers[i];
143 165
144 layer = sun4i_layer_init_one(drm, type); 166 layer = sun4i_layer_init_one(drm, plane);
145 if (IS_ERR(layer)) { 167 if (IS_ERR(layer)) {
146 dev_err(drm->dev, "Couldn't initialize %s plane\n", 168 dev_err(drm->dev, "Couldn't initialize %s plane\n",
147 i ? "overlay" : "primary"); 169 i ? "overlay" : "primary");
@@ -149,10 +171,10 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
149 }; 171 };
150 172
151 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", 173 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
152 i ? "overlay" : "primary", i); 174 i ? "overlay" : "primary", plane->pipe);
153 regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), 175 regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
154 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, 176 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
155 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(i)); 177 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
156 178
157 layer->id = i; 179 layer->id = i;
158 }; 180 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index b84147896294..1dd3d9eabf2e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -161,10 +161,10 @@ struct tv_mode {
161 bool dac3_en; 161 bool dac3_en;
162 bool dac_bit25_en; 162 bool dac_bit25_en;
163 163
164 struct color_gains *color_gains; 164 const struct color_gains *color_gains;
165 struct burst_levels *burst_levels; 165 const struct burst_levels *burst_levels;
166 struct video_levels *video_levels; 166 const struct video_levels *video_levels;
167 struct resync_parameters *resync_params; 167 const struct resync_parameters *resync_params;
168}; 168};
169 169
170struct sun4i_tv { 170struct sun4i_tv {
@@ -178,39 +178,39 @@ struct sun4i_tv {
178 struct sun4i_drv *drv; 178 struct sun4i_drv *drv;
179}; 179};
180 180
181struct video_levels ntsc_video_levels = { 181static const struct video_levels ntsc_video_levels = {
182 .black = 282, .blank = 240, 182 .black = 282, .blank = 240,
183}; 183};
184 184
185struct video_levels pal_video_levels = { 185static const struct video_levels pal_video_levels = {
186 .black = 252, .blank = 252, 186 .black = 252, .blank = 252,
187}; 187};
188 188
189struct burst_levels ntsc_burst_levels = { 189static const struct burst_levels ntsc_burst_levels = {
190 .cb = 79, .cr = 0, 190 .cb = 79, .cr = 0,
191}; 191};
192 192
193struct burst_levels pal_burst_levels = { 193static const struct burst_levels pal_burst_levels = {
194 .cb = 40, .cr = 40, 194 .cb = 40, .cr = 40,
195}; 195};
196 196
197struct color_gains ntsc_color_gains = { 197static const struct color_gains ntsc_color_gains = {
198 .cb = 160, .cr = 160, 198 .cb = 160, .cr = 160,
199}; 199};
200 200
201struct color_gains pal_color_gains = { 201static const struct color_gains pal_color_gains = {
202 .cb = 224, .cr = 224, 202 .cb = 224, .cr = 224,
203}; 203};
204 204
205struct resync_parameters ntsc_resync_parameters = { 205static const struct resync_parameters ntsc_resync_parameters = {
206 .field = false, .line = 14, .pixel = 12, 206 .field = false, .line = 14, .pixel = 12,
207}; 207};
208 208
209struct resync_parameters pal_resync_parameters = { 209static const struct resync_parameters pal_resync_parameters = {
210 .field = true, .line = 13, .pixel = 12, 210 .field = true, .line = 13, .pixel = 12,
211}; 211};
212 212
213struct tv_mode tv_modes[] = { 213static const struct tv_mode tv_modes[] = {
214 { 214 {
215 .name = "NTSC", 215 .name = "NTSC",
216 .mode = SUN4I_TVE_CFG0_RES_480i, 216 .mode = SUN4I_TVE_CFG0_RES_480i,
@@ -289,13 +289,13 @@ drm_connector_to_sun4i_tv(struct drm_connector *connector)
289 * So far, it doesn't seem to be preserved when the mode is passed by 289 * So far, it doesn't seem to be preserved when the mode is passed by
290 * to mode_set for some reason. 290 * to mode_set for some reason.
291 */ 291 */
292static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode) 292static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_mode *mode)
293{ 293{
294 int i; 294 int i;
295 295
296 /* First try to identify the mode by name */ 296 /* First try to identify the mode by name */
297 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { 297 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
298 struct tv_mode *tv_mode = &tv_modes[i]; 298 const struct tv_mode *tv_mode = &tv_modes[i];
299 299
300 DRM_DEBUG_DRIVER("Comparing mode %s vs %s", 300 DRM_DEBUG_DRIVER("Comparing mode %s vs %s",
301 mode->name, tv_mode->name); 301 mode->name, tv_mode->name);
@@ -306,7 +306,7 @@ static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode)
306 306
307 /* Then by number of lines */ 307 /* Then by number of lines */
308 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { 308 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
309 struct tv_mode *tv_mode = &tv_modes[i]; 309 const struct tv_mode *tv_mode = &tv_modes[i];
310 310
311 DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)", 311 DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)",
312 mode->name, tv_mode->name, 312 mode->name, tv_mode->name,
@@ -319,7 +319,7 @@ static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode)
319 return NULL; 319 return NULL;
320} 320}
321 321
322static void sun4i_tv_mode_to_drm_mode(struct tv_mode *tv_mode, 322static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode,
323 struct drm_display_mode *mode) 323 struct drm_display_mode *mode)
324{ 324{
325 DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name); 325 DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name);
@@ -386,7 +386,7 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
386 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); 386 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
387 struct sun4i_drv *drv = tv->drv; 387 struct sun4i_drv *drv = tv->drv;
388 struct sun4i_tcon *tcon = drv->tcon; 388 struct sun4i_tcon *tcon = drv->tcon;
389 struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); 389 const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
390 390
391 sun4i_tcon1_mode_set(tcon, mode); 391 sun4i_tcon1_mode_set(tcon, mode);
392 392
@@ -507,8 +507,14 @@ static int sun4i_tv_comp_get_modes(struct drm_connector *connector)
507 int i; 507 int i;
508 508
509 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { 509 for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
510 struct drm_display_mode *mode = drm_mode_create(connector->dev); 510 struct drm_display_mode *mode;
511 struct tv_mode *tv_mode = &tv_modes[i]; 511 const struct tv_mode *tv_mode = &tv_modes[i];
512
513 mode = drm_mode_create(connector->dev);
514 if (!mode) {
515 DRM_ERROR("Failed to create a new display mode\n");
516 return 0;
517 }
512 518
513 strcpy(mode->name, tv_mode->name); 519 strcpy(mode->name, tv_mode->name);
514 520