1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * linux/drivers/video/mmp/hw/mmp_ctrl.c
4 * Marvell MMP series Display Controller support
6 * Copyright (C) 2012 Marvell Technology Group Ltd.
7 * Authors: Guoqing Li <ligq@marvell.com>
8 * Lisa Du <cldu@marvell.com>
9 * Zhou Zhu <zzhu3@marvell.com>
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/interrupt.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/platform_device.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/clk.h>
22 #include <linux/err.h>
23 #include <linux/vmalloc.h>
24 #include <linux/uaccess.h>
25 #include <linux/kthread.h>
30 static irqreturn_t
ctrl_handle_irq(int irq
, void *dev_id
)
32 struct mmphw_ctrl
*ctrl
= (struct mmphw_ctrl
*)dev_id
;
35 isr
= readl_relaxed(ctrl
->reg_base
+ SPU_IRQ_ISR
);
36 imask
= readl_relaxed(ctrl
->reg_base
+ SPU_IRQ_ENA
);
39 /* clear clock only */
40 tmp
= readl_relaxed(ctrl
->reg_base
+ SPU_IRQ_ISR
);
42 writel_relaxed(~isr
, ctrl
->reg_base
+ SPU_IRQ_ISR
);
43 } while ((isr
= readl_relaxed(ctrl
->reg_base
+ SPU_IRQ_ISR
)) & imask
);
48 static u32
fmt_to_reg(struct mmp_overlay
*overlay
, int pix_fmt
)
50 u32 rbswap
= 0, uvswap
= 0, yuvswap
= 0,
52 vid
= overlay_is_vid(overlay
);
57 case PIXFMT_RGB888PACK
:
58 case PIXFMT_RGB888UNPACK
:
82 case PIXFMT_RGB888PACK
:
83 case PIXFMT_BGR888PACK
:
86 case PIXFMT_RGB888UNPACK
:
87 case PIXFMT_BGR888UNPACK
:
114 return (dma_palette(0) | dma_fmt(vid
, val
) |
115 dma_swaprb(vid
, rbswap
) | dma_swapuv(vid
, uvswap
) |
116 dma_swapyuv(vid
, yuvswap
) | dma_csc(vid
, csc_en
));
119 static void dmafetch_set_fmt(struct mmp_overlay
*overlay
)
122 struct mmp_path
*path
= overlay
->path
;
123 tmp
= readl_relaxed(ctrl_regs(path
) + dma_ctrl(0, path
->id
));
124 tmp
&= ~dma_mask(overlay_is_vid(overlay
));
125 tmp
|= fmt_to_reg(overlay
, overlay
->win
.pix_fmt
);
126 writel_relaxed(tmp
, ctrl_regs(path
) + dma_ctrl(0, path
->id
));
129 static void overlay_set_win(struct mmp_overlay
*overlay
, struct mmp_win
*win
)
131 struct lcd_regs
*regs
= path_regs(overlay
->path
);
133 /* assert win supported */
134 memcpy(&overlay
->win
, win
, sizeof(struct mmp_win
));
136 mutex_lock(&overlay
->access_ok
);
138 if (overlay_is_vid(overlay
)) {
139 writel_relaxed(win
->pitch
[0],
140 (void __iomem
*)®s
->v_pitch_yc
);
141 writel_relaxed(win
->pitch
[2] << 16 | win
->pitch
[1],
142 (void __iomem
*)®s
->v_pitch_uv
);
144 writel_relaxed((win
->ysrc
<< 16) | win
->xsrc
,
145 (void __iomem
*)®s
->v_size
);
146 writel_relaxed((win
->ydst
<< 16) | win
->xdst
,
147 (void __iomem
*)®s
->v_size_z
);
148 writel_relaxed(win
->ypos
<< 16 | win
->xpos
,
149 (void __iomem
*)®s
->v_start
);
151 writel_relaxed(win
->pitch
[0], (void __iomem
*)®s
->g_pitch
);
153 writel_relaxed((win
->ysrc
<< 16) | win
->xsrc
,
154 (void __iomem
*)®s
->g_size
);
155 writel_relaxed((win
->ydst
<< 16) | win
->xdst
,
156 (void __iomem
*)®s
->g_size_z
);
157 writel_relaxed(win
->ypos
<< 16 | win
->xpos
,
158 (void __iomem
*)®s
->g_start
);
161 dmafetch_set_fmt(overlay
);
162 mutex_unlock(&overlay
->access_ok
);
165 static void dmafetch_onoff(struct mmp_overlay
*overlay
, int on
)
167 u32 mask
= overlay_is_vid(overlay
) ? CFG_DMA_ENA_MASK
:
169 u32 enable
= overlay_is_vid(overlay
) ? CFG_DMA_ENA(1) : CFG_GRA_ENA(1);
171 struct mmp_path
*path
= overlay
->path
;
173 mutex_lock(&overlay
->access_ok
);
174 tmp
= readl_relaxed(ctrl_regs(path
) + dma_ctrl(0, path
->id
));
176 tmp
|= (on
? enable
: 0);
177 writel(tmp
, ctrl_regs(path
) + dma_ctrl(0, path
->id
));
178 mutex_unlock(&overlay
->access_ok
);
181 static void path_enabledisable(struct mmp_path
*path
, int on
)
184 mutex_lock(&path
->access_ok
);
185 tmp
= readl_relaxed(ctrl_regs(path
) + LCD_SCLK(path
));
187 tmp
&= ~SCLK_DISABLE
;
190 writel_relaxed(tmp
, ctrl_regs(path
) + LCD_SCLK(path
));
191 mutex_unlock(&path
->access_ok
);
194 static void path_onoff(struct mmp_path
*path
, int on
)
196 if (path
->status
== on
) {
197 dev_info(path
->dev
, "path %s is already %s\n",
198 path
->name
, stat_name(path
->status
));
203 path_enabledisable(path
, 1);
205 if (path
->panel
&& path
->panel
->set_onoff
)
206 path
->panel
->set_onoff(path
->panel
, 1);
208 if (path
->panel
&& path
->panel
->set_onoff
)
209 path
->panel
->set_onoff(path
->panel
, 0);
211 path_enabledisable(path
, 0);
216 static void overlay_set_onoff(struct mmp_overlay
*overlay
, int on
)
218 if (overlay
->status
== on
) {
219 dev_info(overlay_to_ctrl(overlay
)->dev
, "overlay %s is already %s\n",
220 overlay
->path
->name
, stat_name(overlay
->status
));
223 overlay
->status
= on
;
224 dmafetch_onoff(overlay
, on
);
225 if (overlay
->path
->ops
.check_status(overlay
->path
)
226 != overlay
->path
->status
)
227 path_onoff(overlay
->path
, on
);
230 static void overlay_set_fetch(struct mmp_overlay
*overlay
, int fetch_id
)
232 overlay
->dmafetch_id
= fetch_id
;
235 static int overlay_set_addr(struct mmp_overlay
*overlay
, struct mmp_addr
*addr
)
237 struct lcd_regs
*regs
= path_regs(overlay
->path
);
239 /* FIXME: assert addr supported */
240 memcpy(&overlay
->addr
, addr
, sizeof(struct mmp_addr
));
242 if (overlay_is_vid(overlay
)) {
243 writel_relaxed(addr
->phys
[0], (void __iomem
*)®s
->v_y0
);
244 writel_relaxed(addr
->phys
[1], (void __iomem
*)®s
->v_u0
);
245 writel_relaxed(addr
->phys
[2], (void __iomem
*)®s
->v_v0
);
247 writel_relaxed(addr
->phys
[0], (void __iomem
*)®s
->g_0
);
249 return overlay
->addr
.phys
[0];
252 static void path_set_mode(struct mmp_path
*path
, struct mmp_mode
*mode
)
254 struct lcd_regs
*regs
= path_regs(path
);
255 u32 total_x
, total_y
, vsync_ctrl
, tmp
, sclk_src
, sclk_div
,
256 link_config
= path_to_path_plat(path
)->link_config
,
257 dsi_rbswap
= path_to_path_plat(path
)->link_config
;
259 /* FIXME: assert videomode supported */
260 memcpy(&path
->mode
, mode
, sizeof(struct mmp_mode
));
262 mutex_lock(&path
->access_ok
);
264 /* polarity of timing signals */
265 tmp
= readl_relaxed(ctrl_regs(path
) + intf_ctrl(path
->id
)) & 0x1;
266 tmp
|= mode
->vsync_invert
? 0 : 0x8;
267 tmp
|= mode
->hsync_invert
? 0 : 0x4;
268 tmp
|= link_config
& CFG_DUMBMODE_MASK
;
269 tmp
|= CFG_DUMB_ENA(1);
270 writel_relaxed(tmp
, ctrl_regs(path
) + intf_ctrl(path
->id
));
272 /* interface rb_swap setting */
273 tmp
= readl_relaxed(ctrl_regs(path
) + intf_rbswap_ctrl(path
->id
)) &
274 (~(CFG_INTFRBSWAP_MASK
));
275 tmp
|= dsi_rbswap
& CFG_INTFRBSWAP_MASK
;
276 writel_relaxed(tmp
, ctrl_regs(path
) + intf_rbswap_ctrl(path
->id
));
278 writel_relaxed((mode
->yres
<< 16) | mode
->xres
,
279 (void __iomem
*)®s
->screen_active
);
280 writel_relaxed((mode
->left_margin
<< 16) | mode
->right_margin
,
281 (void __iomem
*)®s
->screen_h_porch
);
282 writel_relaxed((mode
->upper_margin
<< 16) | mode
->lower_margin
,
283 (void __iomem
*)®s
->screen_v_porch
);
284 total_x
= mode
->xres
+ mode
->left_margin
+ mode
->right_margin
+
286 total_y
= mode
->yres
+ mode
->upper_margin
+ mode
->lower_margin
+
288 writel_relaxed((total_y
<< 16) | total_x
,
289 (void __iomem
*)®s
->screen_size
);
292 if (path
->output_type
== PATH_OUT_DSI
)
293 vsync_ctrl
= 0x01330133;
295 vsync_ctrl
= ((mode
->xres
+ mode
->right_margin
) << 16)
296 | (mode
->xres
+ mode
->right_margin
);
297 writel_relaxed(vsync_ctrl
, (void __iomem
*)®s
->vsync_ctrl
);
299 /* set pixclock div */
300 sclk_src
= clk_get_rate(path_to_ctrl(path
)->clk
);
301 sclk_div
= sclk_src
/ mode
->pixclock_freq
;
302 if (sclk_div
* mode
->pixclock_freq
< sclk_src
)
305 dev_info(path
->dev
, "%s sclk_src %d sclk_div 0x%x pclk %d\n",
306 __func__
, sclk_src
, sclk_div
, mode
->pixclock_freq
);
308 tmp
= readl_relaxed(ctrl_regs(path
) + LCD_SCLK(path
));
309 tmp
&= ~CLK_INT_DIV_MASK
;
311 writel_relaxed(tmp
, ctrl_regs(path
) + LCD_SCLK(path
));
313 mutex_unlock(&path
->access_ok
);
316 static struct mmp_overlay_ops mmphw_overlay_ops
= {
317 .set_fetch
= overlay_set_fetch
,
318 .set_onoff
= overlay_set_onoff
,
319 .set_win
= overlay_set_win
,
320 .set_addr
= overlay_set_addr
,
323 static void ctrl_set_default(struct mmphw_ctrl
*ctrl
)
328 * LCD Global control(LCD_TOP_CTRL) should be configed before
329 * any other LCD registers read/write, or there maybe issues.
331 tmp
= readl_relaxed(ctrl
->reg_base
+ LCD_TOP_CTRL
);
333 writel_relaxed(tmp
, ctrl
->reg_base
+ LCD_TOP_CTRL
);
336 /* disable all interrupts */
337 irq_mask
= path_imasks(0) | err_imask(0) |
338 path_imasks(1) | err_imask(1);
339 tmp
= readl_relaxed(ctrl
->reg_base
+ SPU_IRQ_ENA
);
342 writel_relaxed(tmp
, ctrl
->reg_base
+ SPU_IRQ_ENA
);
345 static void path_set_default(struct mmp_path
*path
)
347 struct lcd_regs
*regs
= path_regs(path
);
348 u32 dma_ctrl1
, mask
, tmp
, path_config
;
350 path_config
= path_to_path_plat(path
)->path_config
;
352 /* Configure IOPAD: should be parallel only */
353 if (PATH_OUT_PARALLEL
== path
->output_type
) {
354 mask
= CFG_IOPADMODE_MASK
| CFG_BURST_MASK
| CFG_BOUNDARY_MASK
;
355 tmp
= readl_relaxed(ctrl_regs(path
) + SPU_IOPAD_CONTROL
);
358 writel_relaxed(tmp
, ctrl_regs(path
) + SPU_IOPAD_CONTROL
);
361 /* Select path clock source */
362 tmp
= readl_relaxed(ctrl_regs(path
) + LCD_SCLK(path
));
363 tmp
&= ~SCLK_SRC_SEL_MASK
;
365 writel_relaxed(tmp
, ctrl_regs(path
) + LCD_SCLK(path
));
368 * Configure default bits: vsync triggers DMA,
369 * power save enable, configure alpha registers to
370 * display 100% graphics, and set pixel command.
372 dma_ctrl1
= 0x2032ff81;
374 dma_ctrl1
|= CFG_VSYNC_INV_MASK
;
375 writel_relaxed(dma_ctrl1
, ctrl_regs(path
) + dma_ctrl(1, path
->id
));
377 /* Configure default register values */
378 writel_relaxed(0x00000000, (void __iomem
*)®s
->blank_color
);
379 writel_relaxed(0x00000000, (void __iomem
*)®s
->g_1
);
380 writel_relaxed(0x00000000, (void __iomem
*)®s
->g_start
);
383 * 1.enable multiple burst request in DMA AXI
384 * bus arbiter for faster read if not tv path;
385 * 2.enable horizontal smooth filter;
387 mask
= CFG_GRA_HSMOOTH_MASK
| CFG_DMA_HSMOOTH_MASK
| CFG_ARBFAST_ENA(1);
388 tmp
= readl_relaxed(ctrl_regs(path
) + dma_ctrl(0, path
->id
));
390 if (PATH_TV
== path
->id
)
391 tmp
&= ~CFG_ARBFAST_ENA(1);
392 writel_relaxed(tmp
, ctrl_regs(path
) + dma_ctrl(0, path
->id
));
395 static int path_init(struct mmphw_path_plat
*path_plat
,
396 struct mmp_mach_path_config
*config
)
398 struct mmphw_ctrl
*ctrl
= path_plat
->ctrl
;
399 struct mmp_path_info
*path_info
;
400 struct mmp_path
*path
= NULL
;
402 dev_info(ctrl
->dev
, "%s: %s\n", __func__
, config
->name
);
404 /* init driver data */
405 path_info
= kzalloc(sizeof(*path_info
), GFP_KERNEL
);
409 path_info
->name
= config
->name
;
410 path_info
->id
= path_plat
->id
;
411 path_info
->dev
= ctrl
->dev
;
412 path_info
->overlay_num
= config
->overlay_num
;
413 path_info
->overlay_ops
= &mmphw_overlay_ops
;
414 path_info
->set_mode
= path_set_mode
;
415 path_info
->plat_data
= path_plat
;
417 /* create/register platform device */
418 path
= mmp_register_path(path_info
);
423 path_plat
->path
= path
;
424 path_plat
->path_config
= config
->path_config
;
425 path_plat
->link_config
= config
->link_config
;
426 path_plat
->dsi_rbswap
= config
->dsi_rbswap
;
427 path_set_default(path
);
433 static void path_deinit(struct mmphw_path_plat
*path_plat
)
438 mmp_unregister_path(path_plat
->path
);
441 static int mmphw_probe(struct platform_device
*pdev
)
443 struct mmp_mach_plat_info
*mi
;
444 struct resource
*res
;
446 struct mmphw_path_plat
*path_plat
;
447 struct mmphw_ctrl
*ctrl
= NULL
;
449 /* get resources from platform data */
450 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
452 dev_err(&pdev
->dev
, "%s: no IO memory defined\n", __func__
);
457 irq
= platform_get_irq(pdev
, 0);
463 /* get configs from platform data */
464 mi
= pdev
->dev
.platform_data
;
465 if (mi
== NULL
|| !mi
->path_num
|| !mi
->paths
) {
466 dev_err(&pdev
->dev
, "%s: no platform data defined\n", __func__
);
472 ctrl
= devm_kzalloc(&pdev
->dev
,
473 struct_size(ctrl
, path_plats
, mi
->path_num
),
480 ctrl
->name
= mi
->name
;
481 ctrl
->path_num
= mi
->path_num
;
482 ctrl
->dev
= &pdev
->dev
;
484 platform_set_drvdata(pdev
, ctrl
);
485 mutex_init(&ctrl
->access_ok
);
488 if (!devm_request_mem_region(ctrl
->dev
, res
->start
,
489 resource_size(res
), ctrl
->name
)) {
491 "can't request region for resource %pR\n", res
);
496 ctrl
->reg_base
= devm_ioremap(ctrl
->dev
,
497 res
->start
, resource_size(res
));
498 if (ctrl
->reg_base
== NULL
) {
499 dev_err(ctrl
->dev
, "%s: res %pR map failed\n", __func__
, res
);
505 ret
= devm_request_irq(ctrl
->dev
, ctrl
->irq
, ctrl_handle_irq
,
506 IRQF_SHARED
, "lcd_controller", ctrl
);
508 dev_err(ctrl
->dev
, "%s unable to request IRQ %d\n",
509 __func__
, ctrl
->irq
);
515 ctrl
->clk
= devm_clk_get(ctrl
->dev
, mi
->clk_name
);
516 if (IS_ERR(ctrl
->clk
)) {
517 dev_err(ctrl
->dev
, "unable to get clk %s\n", mi
->clk_name
);
521 clk_prepare_enable(ctrl
->clk
);
523 /* init global regs */
524 ctrl_set_default(ctrl
);
526 /* init pathes from machine info and register them */
527 for (i
= 0; i
< ctrl
->path_num
; i
++) {
528 /* get from config and machine info */
529 path_plat
= &ctrl
->path_plats
[i
];
531 path_plat
->ctrl
= ctrl
;
534 if (!path_init(path_plat
, &mi
->paths
[i
])) {
536 goto failed_path_init
;
540 #ifdef CONFIG_MMP_DISP_SPI
541 ret
= lcd_spi_register(ctrl
);
543 goto failed_path_init
;
546 dev_info(ctrl
->dev
, "device init done\n");
551 for (i
= 0; i
< ctrl
->path_num
; i
++) {
552 path_plat
= &ctrl
->path_plats
[i
];
553 path_deinit(path_plat
);
556 clk_disable_unprepare(ctrl
->clk
);
558 dev_err(&pdev
->dev
, "device init failed\n");
563 static struct platform_driver mmphw_driver
= {
567 .probe
= mmphw_probe
,
570 static int mmphw_init(void)
572 return platform_driver_register(&mmphw_driver
);
574 module_init(mmphw_init
);
576 MODULE_AUTHOR("Li Guoqing<ligq@marvell.com>");
577 MODULE_DESCRIPTION("Framebuffer driver for mmp");
578 MODULE_LICENSE("GPL");