Merge tag 'xfs-for-linus-v3.14-rc1-2' of git://oss.sgi.com/xfs/xfs
[linux-2.6-block.git] / drivers / video / sh_mobile_lcdcfb.c
CommitLineData
cfb4f5d1
MD
1/*
2 * SuperH Mobile LCDC Framebuffer
3 *
4 * Copyright (c) 2008 Magnus Damm
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
f1f60b5f
LP
11#include <linux/atomic.h>
12#include <linux/backlight.h>
cfb4f5d1 13#include <linux/clk.h>
f1f60b5f 14#include <linux/console.h>
c5deac3c 15#include <linux/ctype.h>
cfb4f5d1 16#include <linux/dma-mapping.h>
f1f60b5f
LP
17#include <linux/delay.h>
18#include <linux/gpio.h>
19#include <linux/init.h>
8564557a 20#include <linux/interrupt.h>
40331b21 21#include <linux/ioctl.h>
f1f60b5f
LP
22#include <linux/kernel.h>
23#include <linux/mm.h>
355b200b 24#include <linux/module.h>
f1f60b5f
LP
25#include <linux/platform_device.h>
26#include <linux/pm_runtime.h>
27#include <linux/slab.h>
28#include <linux/videodev2.h>
29#include <linux/vmalloc.h>
30
225c9a8d 31#include <video/sh_mobile_lcdc.h>
8a20974f 32#include <video/sh_mobile_meram.h>
cfb4f5d1 33
6de9edd5
GL
34#include "sh_mobile_lcdcfb.h"
35
c5deac3c
LP
36/* ----------------------------------------------------------------------------
37 * Overlay register definitions
38 */
39
40#define LDBCR 0xb00
41#define LDBCR_UPC(n) (1 << ((n) + 16))
42#define LDBCR_UPF(n) (1 << ((n) + 8))
43#define LDBCR_UPD(n) (1 << ((n) + 0))
44#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00)
45#define LDBBSIFR_EN (1 << 31)
46#define LDBBSIFR_VS (1 << 29)
47#define LDBBSIFR_BRSEL (1 << 28)
48#define LDBBSIFR_MX (1 << 27)
49#define LDBBSIFR_MY (1 << 26)
50#define LDBBSIFR_CV3 (3 << 24)
51#define LDBBSIFR_CV2 (2 << 24)
52#define LDBBSIFR_CV1 (1 << 24)
53#define LDBBSIFR_CV0 (0 << 24)
54#define LDBBSIFR_CV_MASK (3 << 24)
55#define LDBBSIFR_LAY_MASK (0xff << 16)
56#define LDBBSIFR_LAY_SHIFT 16
57#define LDBBSIFR_ROP3_MASK (0xff << 16)
58#define LDBBSIFR_ROP3_SHIFT 16
59#define LDBBSIFR_AL_PL8 (3 << 14)
60#define LDBBSIFR_AL_PL1 (2 << 14)
61#define LDBBSIFR_AL_PK (1 << 14)
62#define LDBBSIFR_AL_1 (0 << 14)
63#define LDBBSIFR_AL_MASK (3 << 14)
64#define LDBBSIFR_SWPL (1 << 10)
65#define LDBBSIFR_SWPW (1 << 9)
66#define LDBBSIFR_SWPB (1 << 8)
67#define LDBBSIFR_RY (1 << 7)
68#define LDBBSIFR_CHRR_420 (2 << 0)
69#define LDBBSIFR_CHRR_422 (1 << 0)
70#define LDBBSIFR_CHRR_444 (0 << 0)
71#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0)
72#define LDBBSIFR_RPKF_RGB16 (0x03 << 0)
73#define LDBBSIFR_RPKF_RGB24 (0x0b << 0)
74#define LDBBSIFR_RPKF_MASK (0x1f << 0)
75#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04)
76#define LDBBSSZR_BVSS_MASK (0xfff << 16)
77#define LDBBSSZR_BVSS_SHIFT 16
78#define LDBBSSZR_BHSS_MASK (0xfff << 0)
79#define LDBBSSZR_BHSS_SHIFT 0
80#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08)
81#define LDBBLOCR_CVLC_MASK (0xfff << 16)
82#define LDBBLOCR_CVLC_SHIFT 16
83#define LDBBLOCR_CHLC_MASK (0xfff << 0)
84#define LDBBLOCR_CHLC_SHIFT 0
85#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c)
86#define LDBBSMWR_BSMWA_MASK (0xffff << 16)
87#define LDBBSMWR_BSMWA_SHIFT 16
88#define LDBBSMWR_BSMW_MASK (0xffff << 0)
89#define LDBBSMWR_BSMW_SHIFT 0
90#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10)
91#define LDBBSAYR_FG1A_MASK (0xff << 24)
92#define LDBBSAYR_FG1A_SHIFT 24
93#define LDBBSAYR_FG1R_MASK (0xff << 16)
94#define LDBBSAYR_FG1R_SHIFT 16
95#define LDBBSAYR_FG1G_MASK (0xff << 8)
96#define LDBBSAYR_FG1G_SHIFT 8
97#define LDBBSAYR_FG1B_MASK (0xff << 0)
98#define LDBBSAYR_FG1B_SHIFT 0
99#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14)
100#define LDBBSACR_FG2A_MASK (0xff << 24)
101#define LDBBSACR_FG2A_SHIFT 24
102#define LDBBSACR_FG2R_MASK (0xff << 16)
103#define LDBBSACR_FG2R_SHIFT 16
104#define LDBBSACR_FG2G_MASK (0xff << 8)
105#define LDBBSACR_FG2G_SHIFT 8
106#define LDBBSACR_FG2B_MASK (0xff << 0)
107#define LDBBSACR_FG2B_SHIFT 0
108#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18)
109#define LDBBSAAR_AP_MASK (0xff << 24)
110#define LDBBSAAR_AP_SHIFT 24
111#define LDBBSAAR_R_MASK (0xff << 16)
112#define LDBBSAAR_R_SHIFT 16
113#define LDBBSAAR_GY_MASK (0xff << 8)
114#define LDBBSAAR_GY_SHIFT 8
115#define LDBBSAAR_B_MASK (0xff << 0)
116#define LDBBSAAR_B_SHIFT 0
117#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c)
118#define LDBBPPCR_AP_MASK (0xff << 24)
119#define LDBBPPCR_AP_SHIFT 24
120#define LDBBPPCR_R_MASK (0xff << 16)
121#define LDBBPPCR_R_SHIFT 16
122#define LDBBPPCR_GY_MASK (0xff << 8)
123#define LDBBPPCR_GY_SHIFT 8
124#define LDBBPPCR_B_MASK (0xff << 0)
125#define LDBBPPCR_B_SHIFT 0
126#define LDBnBBGCL(n) (0xb10 + (n) * 0x04)
127#define LDBBBGCL_BGA_MASK (0xff << 24)
128#define LDBBBGCL_BGA_SHIFT 24
129#define LDBBBGCL_BGR_MASK (0xff << 16)
130#define LDBBBGCL_BGR_SHIFT 16
131#define LDBBBGCL_BGG_MASK (0xff << 8)
132#define LDBBBGCL_BGG_SHIFT 8
133#define LDBBBGCL_BGB_MASK (0xff << 0)
134#define LDBBBGCL_BGB_SHIFT 0
135
a6f15ade
PE
136#define SIDE_B_OFFSET 0x1000
137#define MIRROR_OFFSET 0x2000
cfb4f5d1 138
d2ecbab5
GL
139#define MAX_XRES 1920
140#define MAX_YRES 1080
cfb4f5d1 141
c5deac3c
LP
142enum sh_mobile_lcdc_overlay_mode {
143 LCDC_OVERLAY_BLEND,
144 LCDC_OVERLAY_ROP3,
145};
146
147/*
148 * struct sh_mobile_lcdc_overlay - LCDC display overlay
149 *
150 * @channel: LCDC channel this overlay belongs to
151 * @cfg: Overlay configuration
152 * @info: Frame buffer device
153 * @index: Overlay index (0-3)
154 * @base: Overlay registers base address
155 * @enabled: True if the overlay is enabled
156 * @mode: Overlay blending mode (alpha blend or ROP3)
157 * @alpha: Global alpha blending value (0-255, for alpha blending mode)
158 * @rop3: Raster operation (for ROP3 mode)
159 * @fb_mem: Frame buffer virtual memory address
160 * @fb_size: Frame buffer size in bytes
161 * @dma_handle: Frame buffer DMA address
162 * @base_addr_y: Overlay base address (RGB or luma component)
163 * @base_addr_c: Overlay base address (chroma component)
a4aa25f6 164 * @pan_y_offset: Panning linear offset in bytes (luma component)
c5deac3c
LP
165 * @format: Current pixelf format
166 * @xres: Horizontal visible resolution
167 * @xres_virtual: Horizontal total resolution
168 * @yres: Vertical visible resolution
169 * @yres_virtual: Vertical total resolution
170 * @pitch: Overlay line pitch
171 * @pos_x: Horizontal overlay position
172 * @pos_y: Vertical overlay position
173 */
174struct sh_mobile_lcdc_overlay {
175 struct sh_mobile_lcdc_chan *channel;
176
177 const struct sh_mobile_lcdc_overlay_cfg *cfg;
178 struct fb_info *info;
179
180 unsigned int index;
181 unsigned long base;
182
183 bool enabled;
184 enum sh_mobile_lcdc_overlay_mode mode;
185 unsigned int alpha;
186 unsigned int rop3;
187
188 void *fb_mem;
189 unsigned long fb_size;
190
191 dma_addr_t dma_handle;
192 unsigned long base_addr_y;
193 unsigned long base_addr_c;
a4aa25f6 194 unsigned long pan_y_offset;
c5deac3c
LP
195
196 const struct sh_mobile_lcdc_format_info *format;
197 unsigned int xres;
198 unsigned int xres_virtual;
199 unsigned int yres;
200 unsigned int yres_virtual;
201 unsigned int pitch;
202 int pos_x;
203 int pos_y;
204};
205
f1f60b5f
LP
206struct sh_mobile_lcdc_priv {
207 void __iomem *base;
208 int irq;
209 atomic_t hw_usecnt;
210 struct device *dev;
211 struct clk *dot_clk;
212 unsigned long lddckr;
c5deac3c 213
f1f60b5f 214 struct sh_mobile_lcdc_chan ch[2];
c5deac3c
LP
215 struct sh_mobile_lcdc_overlay overlays[4];
216
f1f60b5f
LP
217 struct notifier_block notifier;
218 int started;
219 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
220 struct sh_mobile_meram_info *meram_dev;
221};
222
223/* -----------------------------------------------------------------------------
224 * Registers access
225 */
226
0246c471 227static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
cfb4f5d1
MD
228 [LDDCKPAT1R] = 0x400,
229 [LDDCKPAT2R] = 0x404,
230 [LDMT1R] = 0x418,
231 [LDMT2R] = 0x41c,
232 [LDMT3R] = 0x420,
233 [LDDFR] = 0x424,
234 [LDSM1R] = 0x428,
8564557a 235 [LDSM2R] = 0x42c,
cfb4f5d1 236 [LDSA1R] = 0x430,
53b50314 237 [LDSA2R] = 0x434,
cfb4f5d1
MD
238 [LDMLSR] = 0x438,
239 [LDHCNR] = 0x448,
240 [LDHSYNR] = 0x44c,
241 [LDVLNR] = 0x450,
242 [LDVSYNR] = 0x454,
243 [LDPMR] = 0x460,
6011bdea 244 [LDHAJR] = 0x4a0,
cfb4f5d1
MD
245};
246
0246c471 247static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
cfb4f5d1
MD
248 [LDDCKPAT1R] = 0x408,
249 [LDDCKPAT2R] = 0x40c,
250 [LDMT1R] = 0x600,
251 [LDMT2R] = 0x604,
252 [LDMT3R] = 0x608,
253 [LDDFR] = 0x60c,
254 [LDSM1R] = 0x610,
8564557a 255 [LDSM2R] = 0x614,
cfb4f5d1
MD
256 [LDSA1R] = 0x618,
257 [LDMLSR] = 0x620,
258 [LDHCNR] = 0x624,
259 [LDHSYNR] = 0x628,
260 [LDVLNR] = 0x62c,
261 [LDVSYNR] = 0x630,
262 [LDPMR] = 0x63c,
263};
264
a6f15ade
PE
265static bool banked(int reg_nr)
266{
267 switch (reg_nr) {
268 case LDMT1R:
269 case LDMT2R:
270 case LDMT3R:
271 case LDDFR:
272 case LDSM1R:
273 case LDSA1R:
53b50314 274 case LDSA2R:
a6f15ade
PE
275 case LDMLSR:
276 case LDHCNR:
277 case LDHSYNR:
278 case LDVLNR:
279 case LDVSYNR:
280 return true;
281 }
282 return false;
283}
284
f1f60b5f
LP
285static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
286{
b5ef967d 287 return chan->cfg->chan == LCDC_CHAN_SUBLCD;
f1f60b5f
LP
288}
289
cfb4f5d1
MD
290static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
291 int reg_nr, unsigned long data)
292{
293 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
a6f15ade
PE
294 if (banked(reg_nr))
295 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
296 SIDE_B_OFFSET);
297}
298
299static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
300 int reg_nr, unsigned long data)
301{
302 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
303 MIRROR_OFFSET);
cfb4f5d1
MD
304}
305
306static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
307 int reg_nr)
308{
309 return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
310}
311
c5deac3c
LP
312static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
313 int reg, unsigned long data)
314{
315 iowrite32(data, ovl->channel->lcdc->base + reg);
316 iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
317}
318
cfb4f5d1
MD
319static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
320 unsigned long reg_offs, unsigned long data)
321{
322 iowrite32(data, priv->base + reg_offs);
323}
324
325static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
326 unsigned long reg_offs)
327{
328 return ioread32(priv->base + reg_offs);
329}
330
331static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
332 unsigned long reg_offs,
333 unsigned long mask, unsigned long until)
334{
335 while ((lcdc_read(priv, reg_offs) & mask) != until)
336 cpu_relax();
337}
338
f1f60b5f
LP
339/* -----------------------------------------------------------------------------
340 * Clock management
341 */
342
343static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
cfb4f5d1 344{
f1f60b5f
LP
345 if (atomic_inc_and_test(&priv->hw_usecnt)) {
346 if (priv->dot_clk)
deccd24f 347 clk_prepare_enable(priv->dot_clk);
f1f60b5f
LP
348 pm_runtime_get_sync(priv->dev);
349 if (priv->meram_dev && priv->meram_dev->pdev)
350 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
351 }
cfb4f5d1
MD
352}
353
f1f60b5f
LP
354static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
355{
356 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
357 if (priv->meram_dev && priv->meram_dev->pdev)
358 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
359 pm_runtime_put(priv->dev);
360 if (priv->dot_clk)
deccd24f 361 clk_disable_unprepare(priv->dot_clk);
f1f60b5f
LP
362 }
363}
364
0a7f17aa
LP
365static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
366 int clock_source)
f1f60b5f 367{
4774c12a 368 struct clk *clk;
f1f60b5f
LP
369 char *str;
370
371 switch (clock_source) {
372 case LCDC_CLK_BUS:
373 str = "bus_clk";
374 priv->lddckr = LDDCKR_ICKSEL_BUS;
375 break;
376 case LCDC_CLK_PERIPHERAL:
377 str = "peripheral_clk";
378 priv->lddckr = LDDCKR_ICKSEL_MIPI;
379 break;
380 case LCDC_CLK_EXTERNAL:
381 str = NULL;
382 priv->lddckr = LDDCKR_ICKSEL_HDMI;
383 break;
384 default:
385 return -EINVAL;
386 }
387
4774c12a
LP
388 if (str == NULL)
389 return 0;
390
0a7f17aa 391 clk = clk_get(priv->dev, str);
4774c12a 392 if (IS_ERR(clk)) {
0a7f17aa 393 dev_err(priv->dev, "cannot get dot clock %s\n", str);
4774c12a 394 return PTR_ERR(clk);
f1f60b5f
LP
395 }
396
4774c12a 397 priv->dot_clk = clk;
f1f60b5f
LP
398 return 0;
399}
400
401/* -----------------------------------------------------------------------------
37c5dcc2 402 * Display, panel and deferred I/O
f1f60b5f
LP
403 */
404
cfb4f5d1
MD
405static void lcdc_sys_write_index(void *handle, unsigned long data)
406{
407 struct sh_mobile_lcdc_chan *ch = handle;
408
ce1c0b08
LP
409 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
410 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
411 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
412 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
413 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
cfb4f5d1
MD
414}
415
416static void lcdc_sys_write_data(void *handle, unsigned long data)
417{
418 struct sh_mobile_lcdc_chan *ch = handle;
419
ce1c0b08
LP
420 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
421 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
422 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
423 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
424 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
cfb4f5d1
MD
425}
426
427static unsigned long lcdc_sys_read_data(void *handle)
428{
429 struct sh_mobile_lcdc_chan *ch = handle;
430
ce1c0b08
LP
431 lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
432 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
433 lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
434 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
cfb4f5d1 435 udelay(1);
ce1c0b08 436 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
cfb4f5d1 437
ce1c0b08 438 return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
cfb4f5d1
MD
439}
440
d38d840a 441static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
cfb4f5d1
MD
442 lcdc_sys_write_index,
443 lcdc_sys_write_data,
444 lcdc_sys_read_data,
445};
446
1c6a307a
PM
447static int sh_mobile_lcdc_sginit(struct fb_info *info,
448 struct list_head *pagelist)
449{
450 struct sh_mobile_lcdc_chan *ch = info->par;
58f03d99 451 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
1c6a307a
PM
452 struct page *page;
453 int nr_pages = 0;
454
455 sg_init_table(ch->sglist, nr_pages_max);
456
457 list_for_each_entry(page, pagelist, lru)
458 sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
459
460 return nr_pages;
461}
462
8564557a
MD
463static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
464 struct list_head *pagelist)
465{
466 struct sh_mobile_lcdc_chan *ch = info->par;
b5ef967d 467 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
8564557a
MD
468
469 /* enable clocks before accessing hardware */
470 sh_mobile_lcdc_clk_on(ch->lcdc);
471
5c1a56b5
PM
472 /*
473 * It's possible to get here without anything on the pagelist via
474 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
475 * invocation. In the former case, the acceleration routines are
476 * stepped in to when using the framebuffer console causing the
477 * workqueue to be scheduled without any dirty pages on the list.
478 *
479 * Despite this, a panel update is still needed given that the
480 * acceleration routines have their own methods for writing in
481 * that still need to be updated.
482 *
483 * The fsync() and empty pagelist case could be optimized for,
484 * but we don't bother, as any application exhibiting such
485 * behaviour is fundamentally broken anyways.
486 */
487 if (!list_empty(pagelist)) {
488 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
489
490 /* trigger panel update */
e8363140 491 dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
afaad83b
LP
492 if (panel->start_transfer)
493 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
ce1c0b08 494 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
e8363140
LP
495 dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
496 DMA_TO_DEVICE);
ef61aae4 497 } else {
afaad83b
LP
498 if (panel->start_transfer)
499 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
ce1c0b08 500 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
ef61aae4 501 }
8564557a
MD
502}
503
504static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
505{
506 struct fb_deferred_io *fbdefio = info->fbdefio;
507
508 if (fbdefio)
509 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
510}
511
37c5dcc2
LP
512static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
513{
b5ef967d 514 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
37c5dcc2 515
9a2985e7 516 if (ch->tx_dev) {
458981c3
LP
517 int ret;
518
519 ret = ch->tx_dev->ops->display_on(ch->tx_dev);
520 if (ret < 0)
9a2985e7 521 return;
458981c3
LP
522
523 if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
524 ch->info->state = FBINFO_STATE_SUSPENDED;
9a2985e7
LP
525 }
526
37c5dcc2 527 /* HDMI must be enabled before LCDC configuration */
afaad83b
LP
528 if (panel->display_on)
529 panel->display_on();
37c5dcc2
LP
530}
531
532static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
533{
b5ef967d 534 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
37c5dcc2 535
afaad83b
LP
536 if (panel->display_off)
537 panel->display_off();
9a2985e7
LP
538
539 if (ch->tx_dev)
540 ch->tx_dev->ops->display_off(ch->tx_dev);
37c5dcc2
LP
541}
542
ecd29947
LP
543static bool
544sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
e0c8601a 545 const struct fb_videomode *new_mode)
ecd29947 546{
ecd29947 547 dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
2d04559d
LP
548 ch->display.mode.xres, ch->display.mode.yres,
549 new_mode->xres, new_mode->yres);
ecd29947 550
e0c8601a 551 /* It can be a different monitor with an equal video-mode */
2d04559d 552 if (fb_mode_is_equal(&ch->display.mode, new_mode))
ecd29947 553 return false;
ecd29947
LP
554
555 dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
2d04559d
LP
556 ch->display.mode.yres, new_mode->yres);
557 ch->display.mode = *new_mode;
ecd29947
LP
558
559 return true;
560}
561
d7ad3342
LP
562static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
563 struct fb_info *info);
ecd29947
LP
564
565static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
566 enum sh_mobile_lcdc_entity_event event,
e0c8601a
LP
567 const struct fb_videomode *mode,
568 const struct fb_monspecs *monspec)
ecd29947
LP
569{
570 struct fb_info *info = ch->info;
e0c8601a 571 struct fb_var_screeninfo var;
ecd29947
LP
572 int ret = 0;
573
574 switch (event) {
575 case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
576 /* HDMI plug in */
3a41c5db 577 console_lock();
ecd29947 578 if (lock_fb_info(info)) {
3a41c5db 579
ecd29947 580
2d04559d
LP
581 ch->display.width = monspec->max_x * 10;
582 ch->display.height = monspec->max_y * 10;
e0c8601a
LP
583
584 if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
ecd29947
LP
585 info->state == FBINFO_STATE_RUNNING) {
586 /* First activation with the default monitor.
587 * Just turn on, if we run a resume here, the
588 * logo disappears.
589 */
856e8dfe
LP
590 info->var.width = ch->display.width;
591 info->var.height = ch->display.height;
ecd29947
LP
592 sh_mobile_lcdc_display_on(ch);
593 } else {
594 /* New monitor or have to wake up */
595 fb_set_suspend(info, 0);
596 }
597
3a41c5db 598
ecd29947
LP
599 unlock_fb_info(info);
600 }
3a41c5db 601 console_unlock();
ecd29947
LP
602 break;
603
604 case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
605 /* HDMI disconnect */
3a41c5db 606 console_lock();
ecd29947 607 if (lock_fb_info(info)) {
ecd29947 608 fb_set_suspend(info, 1);
ecd29947
LP
609 unlock_fb_info(info);
610 }
3a41c5db 611 console_unlock();
ecd29947
LP
612 break;
613
614 case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
615 /* Validate a proposed new mode */
e0c8601a
LP
616 fb_videomode_to_var(&var, mode);
617 var.bits_per_pixel = info->var.bits_per_pixel;
618 var.grayscale = info->var.grayscale;
d7ad3342 619 ret = sh_mobile_lcdc_check_var(&var, info);
ecd29947
LP
620 break;
621 }
622
623 return ret;
624}
625
f1f60b5f
LP
626/* -----------------------------------------------------------------------------
627 * Format helpers
628 */
629
105784bb
LP
630struct sh_mobile_lcdc_format_info {
631 u32 fourcc;
632 unsigned int bpp;
633 bool yuv;
634 u32 lddfr;
635};
636
637static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
638 {
639 .fourcc = V4L2_PIX_FMT_RGB565,
640 .bpp = 16,
641 .yuv = false,
642 .lddfr = LDDFR_PKF_RGB16,
643 }, {
644 .fourcc = V4L2_PIX_FMT_BGR24,
645 .bpp = 24,
646 .yuv = false,
647 .lddfr = LDDFR_PKF_RGB24,
648 }, {
649 .fourcc = V4L2_PIX_FMT_BGR32,
650 .bpp = 32,
651 .yuv = false,
652 .lddfr = LDDFR_PKF_ARGB32,
653 }, {
654 .fourcc = V4L2_PIX_FMT_NV12,
655 .bpp = 12,
656 .yuv = true,
657 .lddfr = LDDFR_CC | LDDFR_YF_420,
658 }, {
659 .fourcc = V4L2_PIX_FMT_NV21,
660 .bpp = 12,
661 .yuv = true,
662 .lddfr = LDDFR_CC | LDDFR_YF_420,
663 }, {
664 .fourcc = V4L2_PIX_FMT_NV16,
665 .bpp = 16,
666 .yuv = true,
667 .lddfr = LDDFR_CC | LDDFR_YF_422,
668 }, {
669 .fourcc = V4L2_PIX_FMT_NV61,
670 .bpp = 16,
671 .yuv = true,
672 .lddfr = LDDFR_CC | LDDFR_YF_422,
673 }, {
674 .fourcc = V4L2_PIX_FMT_NV24,
675 .bpp = 24,
676 .yuv = true,
677 .lddfr = LDDFR_CC | LDDFR_YF_444,
678 }, {
679 .fourcc = V4L2_PIX_FMT_NV42,
680 .bpp = 24,
681 .yuv = true,
682 .lddfr = LDDFR_CC | LDDFR_YF_444,
683 },
684};
685
686static const struct sh_mobile_lcdc_format_info *
687sh_mobile_format_info(u32 fourcc)
688{
689 unsigned int i;
690
691 for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
692 if (sh_mobile_format_infos[i].fourcc == fourcc)
693 return &sh_mobile_format_infos[i];
694 }
695
696 return NULL;
697}
698
f1f60b5f
LP
699static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
700{
701 if (var->grayscale > 1)
702 return var->grayscale;
703
704 switch (var->bits_per_pixel) {
705 case 16:
706 return V4L2_PIX_FMT_RGB565;
707 case 24:
708 return V4L2_PIX_FMT_BGR24;
709 case 32:
710 return V4L2_PIX_FMT_BGR32;
711 default:
712 return 0;
713 }
714}
715
716static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
717{
718 return var->grayscale > 1;
719}
720
f1f60b5f
LP
721/* -----------------------------------------------------------------------------
722 * Start, stop and IRQ
723 */
724
8564557a
MD
725static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
726{
727 struct sh_mobile_lcdc_priv *priv = data;
2feb075a 728 struct sh_mobile_lcdc_chan *ch;
9dd38819 729 unsigned long ldintr;
2feb075a
MD
730 int is_sub;
731 int k;
8564557a 732
dc48665f
LP
733 /* Acknowledge interrupts and disable further VSYNC End IRQs. */
734 ldintr = lcdc_read(priv, _LDINTR);
735 lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
8564557a 736
2feb075a 737 /* figure out if this interrupt is for main or sub lcd */
ce1c0b08 738 is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
2feb075a 739
9dd38819 740 /* wake up channel and disable clocks */
2feb075a
MD
741 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
742 ch = &priv->ch[k];
743
744 if (!ch->enabled)
745 continue;
746
dc48665f 747 /* Frame End */
9dd38819
PE
748 if (ldintr & LDINTR_FS) {
749 if (is_sub == lcdc_chan_is_sublcd(ch)) {
750 ch->frame_end = 1;
751 wake_up(&ch->frame_end_wait);
2feb075a 752
9dd38819
PE
753 sh_mobile_lcdc_clk_off(priv);
754 }
755 }
756
757 /* VSYNC End */
40331b21
PE
758 if (ldintr & LDINTR_VES)
759 complete(&ch->vsync_completion);
2feb075a
MD
760 }
761
8564557a
MD
762 return IRQ_HANDLED;
763}
764
d7ad3342 765static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
4976677f
LP
766{
767 unsigned long ldintr;
768 int ret;
769
770 /* Enable VSync End interrupt and be careful not to acknowledge any
771 * pending interrupt.
772 */
773 ldintr = lcdc_read(ch->lcdc, _LDINTR);
774 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
775 lcdc_write(ch->lcdc, _LDINTR, ldintr);
776
777 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
778 msecs_to_jiffies(100));
779 if (!ret)
780 return -ETIMEDOUT;
781
782 return 0;
783}
784
cfb4f5d1
MD
785static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
786 int start)
787{
788 unsigned long tmp = lcdc_read(priv, _LDCNT2R);
789 int k;
790
791 /* start or stop the lcdc */
792 if (start)
ce1c0b08 793 lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
cfb4f5d1 794 else
ce1c0b08 795 lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
cfb4f5d1
MD
796
797 /* wait until power is applied/stopped on all channels */
798 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
799 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
800 while (1) {
ce1c0b08
LP
801 tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
802 & LDPMR_LPS;
803 if (start && tmp == LDPMR_LPS)
cfb4f5d1
MD
804 break;
805 if (!start && tmp == 0)
806 break;
807 cpu_relax();
808 }
809
810 if (!start)
811 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
812}
813
6011bdea
GL
814static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
815{
2d04559d
LP
816 const struct fb_var_screeninfo *var = &ch->info->var;
817 const struct fb_videomode *mode = &ch->display.mode;
1c120deb 818 unsigned long h_total, hsync_pos, display_h_total;
6011bdea
GL
819 u32 tmp;
820
821 tmp = ch->ldmt1r_value;
ce1c0b08
LP
822 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
823 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
b5ef967d
LP
824 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
825 tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
826 tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
827 tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
828 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
6011bdea
GL
829 lcdc_write_chan(ch, LDMT1R, tmp);
830
831 /* setup SYS bus */
b5ef967d
LP
832 lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
833 lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
6011bdea
GL
834
835 /* horizontal configuration */
2d04559d
LP
836 h_total = mode->xres + mode->hsync_len + mode->left_margin
837 + mode->right_margin;
6011bdea 838 tmp = h_total / 8; /* HTCN */
58f03d99 839 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
6011bdea
GL
840 lcdc_write_chan(ch, LDHCNR, tmp);
841
2d04559d 842 hsync_pos = mode->xres + mode->right_margin;
6011bdea 843 tmp = hsync_pos / 8; /* HSYNP */
2d04559d 844 tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
6011bdea
GL
845 lcdc_write_chan(ch, LDHSYNR, tmp);
846
847 /* vertical configuration */
2d04559d
LP
848 tmp = mode->yres + mode->vsync_len + mode->upper_margin
849 + mode->lower_margin; /* VTLN */
58f03d99 850 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
6011bdea
GL
851 lcdc_write_chan(ch, LDVLNR, tmp);
852
2d04559d
LP
853 tmp = mode->yres + mode->lower_margin; /* VSYNP */
854 tmp |= mode->vsync_len << 16; /* VSYNW */
6011bdea
GL
855 lcdc_write_chan(ch, LDVSYNR, tmp);
856
857 /* Adjust horizontal synchronisation for HDMI */
2d04559d
LP
858 display_h_total = mode->xres + mode->hsync_len + mode->left_margin
859 + mode->right_margin;
860 tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
861 | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
6011bdea 862 lcdc_write_chan(ch, LDHAJR, tmp);
9beb09f1 863 lcdc_write_chan_mirror(ch, LDHAJR, tmp);
6011bdea
GL
864}
865
c5deac3c
LP
866static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
867{
868 u32 format = 0;
869
870 if (!ovl->enabled) {
871 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
872 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
873 lcdc_write(ovl->channel->lcdc, LDBCR,
874 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
875 return;
876 }
877
878 ovl->base_addr_y = ovl->dma_handle;
a4aa25f6
LP
879 ovl->base_addr_c = ovl->dma_handle
880 + ovl->xres_virtual * ovl->yres_virtual;
c5deac3c
LP
881
882 switch (ovl->mode) {
883 case LCDC_OVERLAY_BLEND:
884 format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
885 break;
886
887 case LCDC_OVERLAY_ROP3:
888 format = LDBBSIFR_EN | LDBBSIFR_BRSEL
889 | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
890 break;
891 }
892
893 switch (ovl->format->fourcc) {
894 case V4L2_PIX_FMT_RGB565:
895 case V4L2_PIX_FMT_NV21:
896 case V4L2_PIX_FMT_NV61:
897 case V4L2_PIX_FMT_NV42:
898 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
899 break;
900 case V4L2_PIX_FMT_BGR24:
901 case V4L2_PIX_FMT_NV12:
902 case V4L2_PIX_FMT_NV16:
903 case V4L2_PIX_FMT_NV24:
904 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
905 break;
906 case V4L2_PIX_FMT_BGR32:
907 default:
908 format |= LDBBSIFR_SWPL;
909 break;
910 }
911
912 switch (ovl->format->fourcc) {
913 case V4L2_PIX_FMT_RGB565:
914 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
915 break;
916 case V4L2_PIX_FMT_BGR24:
917 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
918 break;
919 case V4L2_PIX_FMT_BGR32:
920 format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
921 break;
922 case V4L2_PIX_FMT_NV12:
923 case V4L2_PIX_FMT_NV21:
924 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
925 break;
926 case V4L2_PIX_FMT_NV16:
927 case V4L2_PIX_FMT_NV61:
928 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
929 break;
930 case V4L2_PIX_FMT_NV24:
931 case V4L2_PIX_FMT_NV42:
932 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
933 break;
934 }
935
936 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
937
938 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
939
940 lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
941 (ovl->yres << LDBBSSZR_BVSS_SHIFT) |
942 (ovl->xres << LDBBSSZR_BHSS_SHIFT));
943 lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
944 (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
945 (ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
946 lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
947 ovl->pitch << LDBBSMWR_BSMW_SHIFT);
948
949 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
950 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
951
952 lcdc_write(ovl->channel->lcdc, LDBCR,
953 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
954}
955
9a217e34 956/*
d7ad3342 957 * __sh_mobile_lcdc_start - Configure and start the LCDC
9a217e34
LP
958 * @priv: LCDC device
959 *
960 * Configure all enabled channels and start the LCDC device. All external
961 * devices (clocks, MERAM, panels, ...) are not touched by this function.
962 */
963static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
cfb4f5d1
MD
964{
965 struct sh_mobile_lcdc_chan *ch;
cfb4f5d1 966 unsigned long tmp;
9a217e34 967 int k, m;
8564557a 968
9a217e34
LP
969 /* Enable LCDC channels. Read data from external memory, avoid using the
970 * BEU for now.
971 */
972 lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
cfb4f5d1 973
9a217e34 974 /* Stop the LCDC first and disable all interrupts. */
cfb4f5d1 975 sh_mobile_lcdc_start_stop(priv, 0);
9a217e34 976 lcdc_write(priv, _LDINTR, 0);
cfb4f5d1 977
9a217e34 978 /* Configure power supply, dot clocks and start them. */
cfb4f5d1
MD
979 tmp = priv->lddckr;
980 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
981 ch = &priv->ch[k];
9a217e34 982 if (!ch->enabled)
cfb4f5d1
MD
983 continue;
984
9a217e34
LP
985 /* Power supply */
986 lcdc_write_chan(ch, LDPMR, 0);
987
b5ef967d 988 m = ch->cfg->clock_divider;
cfb4f5d1
MD
989 if (!m)
990 continue;
991
505c7de5
LP
992 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
993 * denominator.
994 */
995 lcdc_write_chan(ch, LDDCKPAT1R, 0);
996 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
997
cfb4f5d1 998 if (m == 1)
ce1c0b08 999 m = LDDCKR_MOSEL;
cfb4f5d1 1000 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
cfb4f5d1
MD
1001 }
1002
1003 lcdc_write(priv, _LDDCKR, tmp);
cfb4f5d1
MD
1004 lcdc_write(priv, _LDDCKSTPR, 0);
1005 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
1006
9a217e34 1007 /* Setup geometry, format, frame buffer memory and operation mode. */
cfb4f5d1
MD
1008 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1009 ch = &priv->ch[k];
cfb4f5d1
MD
1010 if (!ch->enabled)
1011 continue;
1012
6011bdea 1013 sh_mobile_lcdc_geometry(ch);
cfb4f5d1 1014
fc9e78e6 1015 tmp = ch->format->lddfr;
edd153a3 1016
fc9e78e6 1017 if (ch->format->yuv) {
58f03d99 1018 switch (ch->colorspace) {
edd153a3
LP
1019 case V4L2_COLORSPACE_REC709:
1020 tmp |= LDDFR_CF1;
53b50314 1021 break;
edd153a3
LP
1022 case V4L2_COLORSPACE_JPEG:
1023 tmp |= LDDFR_CF0;
53b50314
DHG
1024 break;
1025 }
417d4827 1026 }
7caa4342 1027
9a217e34 1028 lcdc_write_chan(ch, LDDFR, tmp);
72c04af9 1029 lcdc_write_chan(ch, LDMLSR, ch->line_size);
9a217e34 1030 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
fc9e78e6 1031 if (ch->format->yuv)
9a217e34 1032 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
7caa4342 1033
9a217e34
LP
1034 /* When using deferred I/O mode, configure the LCDC for one-shot
1035 * operation and enable the frame end interrupt. Otherwise use
1036 * continuous read mode.
1037 */
1038 if (ch->ldmt1r_value & LDMT1R_IFM &&
b5ef967d 1039 ch->cfg->sys_bus_cfg.deferred_io_msec) {
9a217e34
LP
1040 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
1041 lcdc_write(priv, _LDINTR, LDINTR_FE);
1042 } else {
1043 lcdc_write_chan(ch, LDSM1R, 0);
1044 }
1045 }
7caa4342 1046
9a217e34 1047 /* Word and long word swap. */
fc9e78e6 1048 switch (priv->ch[0].format->fourcc) {
edd153a3
LP
1049 case V4L2_PIX_FMT_RGB565:
1050 case V4L2_PIX_FMT_NV21:
1051 case V4L2_PIX_FMT_NV61:
1052 case V4L2_PIX_FMT_NV42:
1053 tmp = LDDDSR_LS | LDDDSR_WS;
1054 break;
1055 case V4L2_PIX_FMT_BGR24:
1056 case V4L2_PIX_FMT_NV12:
1057 case V4L2_PIX_FMT_NV16:
1058 case V4L2_PIX_FMT_NV24:
9a217e34 1059 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
edd153a3
LP
1060 break;
1061 case V4L2_PIX_FMT_BGR32:
1062 default:
1063 tmp = LDDDSR_LS;
1064 break;
9a217e34
LP
1065 }
1066 lcdc_write(priv, _LDDDSR, tmp);
7caa4342 1067
9a217e34
LP
1068 /* Enable the display output. */
1069 lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
1070 sh_mobile_lcdc_start_stop(priv, 1);
1071 priv->started = 1;
1072}
cfb4f5d1 1073
9a217e34
LP
1074static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
1075{
1076 struct sh_mobile_meram_info *mdev = priv->meram_dev;
9a217e34
LP
1077 struct sh_mobile_lcdc_chan *ch;
1078 unsigned long tmp;
1079 int ret;
1080 int k;
cfb4f5d1 1081
9a217e34
LP
1082 /* enable clocks before accessing the hardware */
1083 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1084 if (priv->ch[k].enabled)
1085 sh_mobile_lcdc_clk_on(priv);
1086 }
8564557a 1087
9a217e34
LP
1088 /* reset */
1089 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
1090 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
8564557a 1091
9a217e34 1092 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
b5ef967d 1093 const struct sh_mobile_lcdc_panel_cfg *panel;
8564557a 1094
37c5dcc2 1095 ch = &priv->ch[k];
9a217e34
LP
1096 if (!ch->enabled)
1097 continue;
1098
b5ef967d 1099 panel = &ch->cfg->panel_cfg;
afaad83b
LP
1100 if (panel->setup_sys) {
1101 ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
9a217e34
LP
1102 if (ret)
1103 return ret;
8564557a 1104 }
cfb4f5d1
MD
1105 }
1106
9a217e34
LP
1107 /* Compute frame buffer base address and pitch for each channel. */
1108 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
9a217e34 1109 int pixelformat;
4a237177 1110 void *cache;
cfb4f5d1 1111
9a217e34
LP
1112 ch = &priv->ch[k];
1113 if (!ch->enabled)
1114 continue;
cfb4f5d1 1115
58f03d99 1116 ch->base_addr_y = ch->dma_handle;
a4aa25f6
LP
1117 ch->base_addr_c = ch->dma_handle
1118 + ch->xres_virtual * ch->yres_virtual;
72c04af9 1119 ch->line_size = ch->pitch;
9a217e34
LP
1120
1121 /* Enable MERAM if possible. */
6e729b41 1122 if (mdev == NULL || ch->cfg->meram_cfg == NULL)
9a217e34
LP
1123 continue;
1124
4a237177
LP
1125 /* Free the allocated MERAM cache. */
1126 if (ch->cache) {
6e729b41 1127 sh_mobile_meram_cache_free(mdev, ch->cache);
4a237177 1128 ch->cache = NULL;
9a217e34
LP
1129 }
1130
fc9e78e6 1131 switch (ch->format->fourcc) {
edd153a3
LP
1132 case V4L2_PIX_FMT_NV12:
1133 case V4L2_PIX_FMT_NV21:
1134 case V4L2_PIX_FMT_NV16:
1135 case V4L2_PIX_FMT_NV61:
9a217e34 1136 pixelformat = SH_MOBILE_MERAM_PF_NV;
edd153a3
LP
1137 break;
1138 case V4L2_PIX_FMT_NV24:
1139 case V4L2_PIX_FMT_NV42:
1140 pixelformat = SH_MOBILE_MERAM_PF_NV24;
1141 break;
1142 case V4L2_PIX_FMT_RGB565:
1143 case V4L2_PIX_FMT_BGR24:
1144 case V4L2_PIX_FMT_BGR32:
1145 default:
1146 pixelformat = SH_MOBILE_MERAM_PF_RGB;
1147 break;
1148 }
9a217e34 1149
6e729b41 1150 cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
b5ef967d 1151 ch->pitch, ch->yres, pixelformat,
72c04af9 1152 &ch->line_size);
4a237177 1153 if (!IS_ERR(cache)) {
6e729b41 1154 sh_mobile_meram_cache_update(mdev, cache,
97d16fe6
LP
1155 ch->base_addr_y, ch->base_addr_c,
1156 &ch->base_addr_y, &ch->base_addr_c);
4a237177 1157 ch->cache = cache;
97d16fe6 1158 }
9a217e34
LP
1159 }
1160
c5deac3c
LP
1161 for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
1162 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
1163 sh_mobile_lcdc_overlay_setup(ovl);
1164 }
1165
9a217e34
LP
1166 /* Start the LCDC. */
1167 __sh_mobile_lcdc_start(priv);
1168
1169 /* Setup deferred I/O, tell the board code to enable the panels, and
1170 * turn backlight on.
1171 */
cfb4f5d1
MD
1172 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1173 ch = &priv->ch[k];
21bc1f02
MD
1174 if (!ch->enabled)
1175 continue;
1176
b5ef967d 1177 tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
9a217e34
LP
1178 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
1179 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
1180 ch->defio.delay = msecs_to_jiffies(tmp);
1181 ch->info->fbdefio = &ch->defio;
1182 fb_deferred_io_init(ch->info);
1183 }
1184
37c5dcc2 1185 sh_mobile_lcdc_display_on(ch);
3b0fd9d7
AC
1186
1187 if (ch->bl) {
1188 ch->bl->props.power = FB_BLANK_UNBLANK;
1189 backlight_update_status(ch->bl);
1190 }
cfb4f5d1
MD
1191 }
1192
1193 return 0;
1194}
1195
1196static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
1197{
1198 struct sh_mobile_lcdc_chan *ch;
cfb4f5d1
MD
1199 int k;
1200
2feb075a 1201 /* clean up deferred io and ask board code to disable panel */
cfb4f5d1
MD
1202 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1203 ch = &priv->ch[k];
21bc1f02
MD
1204 if (!ch->enabled)
1205 continue;
8564557a 1206
2feb075a
MD
1207 /* deferred io mode:
1208 * flush frame, and wait for frame end interrupt
1209 * clean up deferred io and enable clock
1210 */
5ef6b505 1211 if (ch->info && ch->info->fbdefio) {
2feb075a 1212 ch->frame_end = 0;
e33afddc 1213 schedule_delayed_work(&ch->info->deferred_work, 0);
2feb075a 1214 wait_event(ch->frame_end_wait, ch->frame_end);
e33afddc
PM
1215 fb_deferred_io_cleanup(ch->info);
1216 ch->info->fbdefio = NULL;
2feb075a 1217 sh_mobile_lcdc_clk_on(priv);
8564557a 1218 }
2feb075a 1219
3b0fd9d7
AC
1220 if (ch->bl) {
1221 ch->bl->props.power = FB_BLANK_POWERDOWN;
1222 backlight_update_status(ch->bl);
1223 }
1224
37c5dcc2 1225 sh_mobile_lcdc_display_off(ch);
7caa4342 1226
4a237177
LP
1227 /* Free the MERAM cache. */
1228 if (ch->cache) {
6e729b41 1229 sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
40af1eb5 1230 ch->cache = NULL;
7caa4342
D
1231 }
1232
cfb4f5d1
MD
1233 }
1234
1235 /* stop the lcdc */
8e9bb19e
MD
1236 if (priv->started) {
1237 sh_mobile_lcdc_start_stop(priv, 0);
1238 priv->started = 0;
1239 }
b51339ff 1240
8564557a
MD
1241 /* stop clocks */
1242 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
1243 if (priv->ch[k].enabled)
1244 sh_mobile_lcdc_clk_off(priv);
cfb4f5d1
MD
1245}
1246
c5deac3c
LP
1247static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
1248 struct fb_info *info)
1249{
1250 if (var->xres > MAX_XRES || var->yres > MAX_YRES)
1251 return -EINVAL;
1252
1253 /* Make sure the virtual resolution is at least as big as the visible
1254 * resolution.
1255 */
1256 if (var->xres_virtual < var->xres)
1257 var->xres_virtual = var->xres;
1258 if (var->yres_virtual < var->yres)
1259 var->yres_virtual = var->yres;
1260
1261 if (sh_mobile_format_is_fourcc(var)) {
1262 const struct sh_mobile_lcdc_format_info *format;
1263
1264 format = sh_mobile_format_info(var->grayscale);
1265 if (format == NULL)
1266 return -EINVAL;
1267 var->bits_per_pixel = format->bpp;
1268
1269 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1270 * respectively.
1271 */
1272 if (!format->yuv)
1273 var->colorspace = V4L2_COLORSPACE_SRGB;
1274 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1275 var->colorspace = V4L2_COLORSPACE_JPEG;
1276 } else {
1277 if (var->bits_per_pixel <= 16) { /* RGB 565 */
1278 var->bits_per_pixel = 16;
1279 var->red.offset = 11;
1280 var->red.length = 5;
1281 var->green.offset = 5;
1282 var->green.length = 6;
1283 var->blue.offset = 0;
1284 var->blue.length = 5;
1285 var->transp.offset = 0;
1286 var->transp.length = 0;
1287 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
1288 var->bits_per_pixel = 24;
1289 var->red.offset = 16;
1290 var->red.length = 8;
1291 var->green.offset = 8;
1292 var->green.length = 8;
1293 var->blue.offset = 0;
1294 var->blue.length = 8;
1295 var->transp.offset = 0;
1296 var->transp.length = 0;
1297 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
1298 var->bits_per_pixel = 32;
1299 var->red.offset = 16;
1300 var->red.length = 8;
1301 var->green.offset = 8;
1302 var->green.length = 8;
1303 var->blue.offset = 0;
1304 var->blue.length = 8;
1305 var->transp.offset = 24;
1306 var->transp.length = 8;
1307 } else
1308 return -EINVAL;
1309
1310 var->red.msb_right = 0;
1311 var->green.msb_right = 0;
1312 var->blue.msb_right = 0;
1313 var->transp.msb_right = 0;
1314 }
1315
1316 /* Make sure we don't exceed our allocated memory. */
1317 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
1318 info->fix.smem_len)
1319 return -EINVAL;
1320
1321 return 0;
1322}
1323
1324/* -----------------------------------------------------------------------------
1325 * Frame buffer operations - Overlays
1326 */
1327
1328static ssize_t
1329overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
1330{
1331 struct fb_info *info = dev_get_drvdata(dev);
1332 struct sh_mobile_lcdc_overlay *ovl = info->par;
1333
1334 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
1335}
1336
1337static ssize_t
1338overlay_alpha_store(struct device *dev, struct device_attribute *attr,
1339 const char *buf, size_t count)
1340{
1341 struct fb_info *info = dev_get_drvdata(dev);
1342 struct sh_mobile_lcdc_overlay *ovl = info->par;
1343 unsigned int alpha;
1344 char *endp;
1345
1346 alpha = simple_strtoul(buf, &endp, 10);
1347 if (isspace(*endp))
1348 endp++;
1349
1350 if (endp - buf != count)
1351 return -EINVAL;
1352
1353 if (alpha > 255)
1354 return -EINVAL;
1355
1356 if (ovl->alpha != alpha) {
1357 ovl->alpha = alpha;
1358
1359 if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
1360 sh_mobile_lcdc_overlay_setup(ovl);
1361 }
1362
1363 return count;
1364}
1365
1366static ssize_t
1367overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
1368{
1369 struct fb_info *info = dev_get_drvdata(dev);
1370 struct sh_mobile_lcdc_overlay *ovl = info->par;
1371
1372 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
1373}
1374
1375static ssize_t
1376overlay_mode_store(struct device *dev, struct device_attribute *attr,
1377 const char *buf, size_t count)
1378{
1379 struct fb_info *info = dev_get_drvdata(dev);
1380 struct sh_mobile_lcdc_overlay *ovl = info->par;
1381 unsigned int mode;
1382 char *endp;
1383
1384 mode = simple_strtoul(buf, &endp, 10);
1385 if (isspace(*endp))
1386 endp++;
1387
1388 if (endp - buf != count)
1389 return -EINVAL;
1390
1391 if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
1392 return -EINVAL;
1393
1394 if (ovl->mode != mode) {
1395 ovl->mode = mode;
1396
1397 if (ovl->enabled)
1398 sh_mobile_lcdc_overlay_setup(ovl);
1399 }
1400
1401 return count;
1402}
1403
1404static ssize_t
1405overlay_position_show(struct device *dev, struct device_attribute *attr,
1406 char *buf)
1407{
1408 struct fb_info *info = dev_get_drvdata(dev);
1409 struct sh_mobile_lcdc_overlay *ovl = info->par;
1410
1411 return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
1412}
1413
1414static ssize_t
1415overlay_position_store(struct device *dev, struct device_attribute *attr,
1416 const char *buf, size_t count)
1417{
1418 struct fb_info *info = dev_get_drvdata(dev);
1419 struct sh_mobile_lcdc_overlay *ovl = info->par;
1420 char *endp;
1421 int pos_x;
1422 int pos_y;
1423
1424 pos_x = simple_strtol(buf, &endp, 10);
1425 if (*endp != ',')
1426 return -EINVAL;
1427
1428 pos_y = simple_strtol(endp + 1, &endp, 10);
1429 if (isspace(*endp))
1430 endp++;
1431
1432 if (endp - buf != count)
1433 return -EINVAL;
1434
1435 if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
1436 ovl->pos_x = pos_x;
1437 ovl->pos_y = pos_y;
1438
1439 if (ovl->enabled)
1440 sh_mobile_lcdc_overlay_setup(ovl);
1441 }
1442
1443 return count;
1444}
1445
1446static ssize_t
1447overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
1448{
1449 struct fb_info *info = dev_get_drvdata(dev);
1450 struct sh_mobile_lcdc_overlay *ovl = info->par;
1451
1452 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
1453}
1454
1455static ssize_t
1456overlay_rop3_store(struct device *dev, struct device_attribute *attr,
1457 const char *buf, size_t count)
1458{
1459 struct fb_info *info = dev_get_drvdata(dev);
1460 struct sh_mobile_lcdc_overlay *ovl = info->par;
1461 unsigned int rop3;
1462 char *endp;
1463
1464 rop3 = !!simple_strtoul(buf, &endp, 10);
1465 if (isspace(*endp))
1466 endp++;
1467
1468 if (endp - buf != count)
1469 return -EINVAL;
1470
1471 if (rop3 > 255)
1472 return -EINVAL;
1473
1474 if (ovl->rop3 != rop3) {
1475 ovl->rop3 = rop3;
1476
1477 if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
1478 sh_mobile_lcdc_overlay_setup(ovl);
1479 }
1480
1481 return count;
1482}
1483
1484static const struct device_attribute overlay_sysfs_attrs[] = {
1485 __ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
1486 overlay_alpha_show, overlay_alpha_store),
1487 __ATTR(ovl_mode, S_IRUGO|S_IWUSR,
1488 overlay_mode_show, overlay_mode_store),
1489 __ATTR(ovl_position, S_IRUGO|S_IWUSR,
1490 overlay_position_show, overlay_position_store),
1491 __ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
1492 overlay_rop3_show, overlay_rop3_store),
1493};
1494
1495static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = {
1496 .id = "SH Mobile LCDC",
1497 .type = FB_TYPE_PACKED_PIXELS,
1498 .visual = FB_VISUAL_TRUECOLOR,
1499 .accel = FB_ACCEL_NONE,
15dede88 1500 .xpanstep = 1,
c5deac3c
LP
1501 .ypanstep = 1,
1502 .ywrapstep = 0,
1503 .capabilities = FB_CAP_FOURCC,
1504};
1505
1506static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
1507 struct fb_info *info)
1508{
1509 struct sh_mobile_lcdc_overlay *ovl = info->par;
1510 unsigned long base_addr_y;
1511 unsigned long base_addr_c;
a4aa25f6 1512 unsigned long y_offset;
c5deac3c
LP
1513 unsigned long c_offset;
1514
a4aa25f6
LP
1515 if (!ovl->format->yuv) {
1516 y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
1517 * ovl->format->bpp / 8;
1518 c_offset = 0;
1519 } else {
1520 unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
1521 unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
1522
1523 y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
1524 c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
1525 + var->xoffset * 2 / xsub;
1526 }
c5deac3c 1527
a4aa25f6
LP
1528 /* If the Y offset hasn't changed, the C offset hasn't either. There's
1529 * nothing to do in that case.
1530 */
1531 if (y_offset == ovl->pan_y_offset)
1532 return 0;
c5deac3c
LP
1533
1534 /* Set the source address for the next refresh */
a4aa25f6
LP
1535 base_addr_y = ovl->dma_handle + y_offset;
1536 base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
1537 + c_offset;
c5deac3c
LP
1538
1539 ovl->base_addr_y = base_addr_y;
a4aa25f6
LP
1540 ovl->base_addr_c = base_addr_c;
1541 ovl->pan_y_offset = y_offset;
c5deac3c 1542
8be7c669
LP
1543 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
1544
c5deac3c
LP
1545 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
1546 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
1547
8be7c669
LP
1548 lcdc_write(ovl->channel->lcdc, LDBCR,
1549 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
1550
c5deac3c
LP
1551 return 0;
1552}
1553
1554static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
1555 unsigned long arg)
1556{
1557 struct sh_mobile_lcdc_overlay *ovl = info->par;
1558
1559 switch (cmd) {
1560 case FBIO_WAITFORVSYNC:
1561 return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
1562
1563 default:
1564 return -ENOIOCTLCMD;
1565 }
1566}
1567
1568static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
1569 struct fb_info *info)
1570{
1571 return __sh_mobile_lcdc_check_var(var, info);
1572}
1573
1574static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
1575{
1576 struct sh_mobile_lcdc_overlay *ovl = info->par;
1577
1578 ovl->format =
1579 sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
1580
1581 ovl->xres = info->var.xres;
1582 ovl->xres_virtual = info->var.xres_virtual;
1583 ovl->yres = info->var.yres;
1584 ovl->yres_virtual = info->var.yres_virtual;
1585
1586 if (ovl->format->yuv)
16ca21c9 1587 ovl->pitch = info->var.xres_virtual;
c5deac3c 1588 else
16ca21c9 1589 ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
c5deac3c
LP
1590
1591 sh_mobile_lcdc_overlay_setup(ovl);
1592
1593 info->fix.line_length = ovl->pitch;
1594
1595 if (sh_mobile_format_is_fourcc(&info->var)) {
1596 info->fix.type = FB_TYPE_FOURCC;
1597 info->fix.visual = FB_VISUAL_FOURCC;
1598 } else {
1599 info->fix.type = FB_TYPE_PACKED_PIXELS;
1600 info->fix.visual = FB_VISUAL_TRUECOLOR;
1601 }
1602
1603 return 0;
1604}
1605
1606/* Overlay blanking. Disable the overlay when blanked. */
1607static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
1608{
1609 struct sh_mobile_lcdc_overlay *ovl = info->par;
1610
1611 ovl->enabled = !blank;
1612 sh_mobile_lcdc_overlay_setup(ovl);
1613
1614 /* Prevent the backlight from receiving a blanking event by returning
1615 * a non-zero value.
1616 */
1617 return 1;
1618}
1619
bf10a537
HE
1620static int
1621sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
1622{
1623 struct sh_mobile_lcdc_overlay *ovl = info->par;
1624
1625 return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
1626 ovl->dma_handle, ovl->fb_size);
1627}
1628
c5deac3c
LP
1629static struct fb_ops sh_mobile_lcdc_overlay_ops = {
1630 .owner = THIS_MODULE,
1631 .fb_read = fb_sys_read,
1632 .fb_write = fb_sys_write,
1633 .fb_fillrect = sys_fillrect,
1634 .fb_copyarea = sys_copyarea,
1635 .fb_imageblit = sys_imageblit,
1636 .fb_blank = sh_mobile_lcdc_overlay_blank,
1637 .fb_pan_display = sh_mobile_lcdc_overlay_pan,
1638 .fb_ioctl = sh_mobile_lcdc_overlay_ioctl,
1639 .fb_check_var = sh_mobile_lcdc_overlay_check_var,
1640 .fb_set_par = sh_mobile_lcdc_overlay_set_par,
bf10a537 1641 .fb_mmap = sh_mobile_lcdc_overlay_mmap,
c5deac3c
LP
1642};
1643
1644static void
1645sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
1646{
1647 struct fb_info *info = ovl->info;
1648
1649 if (info == NULL || info->dev == NULL)
1650 return;
1651
1652 unregister_framebuffer(ovl->info);
1653}
1654
48c68c4f 1655static int
c5deac3c
LP
1656sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
1657{
1658 struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
1659 struct fb_info *info = ovl->info;
1660 unsigned int i;
1661 int ret;
1662
1663 if (info == NULL)
1664 return 0;
1665
1666 ret = register_framebuffer(info);
1667 if (ret < 0)
1668 return ret;
1669
1670 dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
1671 dev_name(lcdc->dev), ovl->index, info->var.xres,
1672 info->var.yres, info->var.bits_per_pixel);
1673
1674 for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
1675 ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
1676 if (ret < 0)
1677 return ret;
1678 }
1679
1680 return 0;
1681}
1682
1683static void
1684sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
1685{
1686 struct fb_info *info = ovl->info;
1687
1688 if (info == NULL || info->device == NULL)
1689 return;
1690
1691 framebuffer_release(info);
1692}
1693
48c68c4f 1694static int
c5deac3c
LP
1695sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
1696{
1697 struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
1698 struct fb_var_screeninfo *var;
1699 struct fb_info *info;
1700
1701 /* Allocate and initialize the frame buffer device. */
1702 info = framebuffer_alloc(0, priv->dev);
1703 if (info == NULL) {
1704 dev_err(priv->dev, "unable to allocate fb_info\n");
1705 return -ENOMEM;
1706 }
1707
1708 ovl->info = info;
1709
1710 info->flags = FBINFO_FLAG_DEFAULT;
1711 info->fbops = &sh_mobile_lcdc_overlay_ops;
1712 info->device = priv->dev;
1713 info->screen_base = ovl->fb_mem;
1714 info->par = ovl;
1715
1716 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1717 * for NV12 and NV21.
1718 */
1719 info->fix = sh_mobile_lcdc_overlay_fix;
1720 snprintf(info->fix.id, sizeof(info->fix.id),
1721 "SH Mobile LCDC Overlay %u", ovl->index);
1722 info->fix.smem_start = ovl->dma_handle;
1723 info->fix.smem_len = ovl->fb_size;
1724 info->fix.line_length = ovl->pitch;
1725
1726 if (ovl->format->yuv)
1727 info->fix.visual = FB_VISUAL_FOURCC;
1728 else
1729 info->fix.visual = FB_VISUAL_TRUECOLOR;
1730
15dede88 1731 switch (ovl->format->fourcc) {
15dede88
LP
1732 case V4L2_PIX_FMT_NV12:
1733 case V4L2_PIX_FMT_NV21:
ac33a207
LP
1734 info->fix.ypanstep = 2;
1735 case V4L2_PIX_FMT_NV16:
1736 case V4L2_PIX_FMT_NV61:
15dede88
LP
1737 info->fix.xpanstep = 2;
1738 }
c5deac3c
LP
1739
1740 /* Initialize variable screen information. */
1741 var = &info->var;
1742 memset(var, 0, sizeof(*var));
1743 var->xres = ovl->xres;
1744 var->yres = ovl->yres;
1745 var->xres_virtual = ovl->xres_virtual;
1746 var->yres_virtual = ovl->yres_virtual;
1747 var->activate = FB_ACTIVATE_NOW;
1748
1749 /* Use the legacy API by default for RGB formats, and the FOURCC API
1750 * for YUV formats.
1751 */
1752 if (!ovl->format->yuv)
1753 var->bits_per_pixel = ovl->format->bpp;
1754 else
1755 var->grayscale = ovl->format->fourcc;
1756
1757 return sh_mobile_lcdc_overlay_check_var(var, info);
1758}
1759
f1f60b5f 1760/* -----------------------------------------------------------------------------
c5deac3c 1761 * Frame buffer operations - main frame buffer
f1f60b5f 1762 */
cfb4f5d1
MD
1763
1764static int sh_mobile_lcdc_setcolreg(u_int regno,
1765 u_int red, u_int green, u_int blue,
1766 u_int transp, struct fb_info *info)
1767{
1768 u32 *palette = info->pseudo_palette;
1769
1770 if (regno >= PALETTE_NR)
1771 return -EINVAL;
1772
1773 /* only FB_VISUAL_TRUECOLOR supported */
1774
1775 red >>= 16 - info->var.red.length;
1776 green >>= 16 - info->var.green.length;
1777 blue >>= 16 - info->var.blue.length;
1778 transp >>= 16 - info->var.transp.length;
1779
1780 palette[regno] = (red << info->var.red.offset) |
1781 (green << info->var.green.offset) |
1782 (blue << info->var.blue.offset) |
1783 (transp << info->var.transp.offset);
1784
1785 return 0;
1786}
1787
3281e54c 1788static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
cfb4f5d1
MD
1789 .id = "SH Mobile LCDC",
1790 .type = FB_TYPE_PACKED_PIXELS,
1791 .visual = FB_VISUAL_TRUECOLOR,
1792 .accel = FB_ACCEL_NONE,
15dede88 1793 .xpanstep = 1,
9dd38819
PE
1794 .ypanstep = 1,
1795 .ywrapstep = 0,
edd153a3 1796 .capabilities = FB_CAP_FOURCC,
cfb4f5d1
MD
1797};
1798
8564557a
MD
1799static void sh_mobile_lcdc_fillrect(struct fb_info *info,
1800 const struct fb_fillrect *rect)
1801{
1802 sys_fillrect(info, rect);
1803 sh_mobile_lcdc_deferred_io_touch(info);
1804}
1805
1806static void sh_mobile_lcdc_copyarea(struct fb_info *info,
1807 const struct fb_copyarea *area)
1808{
1809 sys_copyarea(info, area);
1810 sh_mobile_lcdc_deferred_io_touch(info);
1811}
1812
1813static void sh_mobile_lcdc_imageblit(struct fb_info *info,
1814 const struct fb_image *image)
1815{
1816 sys_imageblit(info, image);
1817 sh_mobile_lcdc_deferred_io_touch(info);
1818}
1819
d7ad3342
LP
1820static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
1821 struct fb_info *info)
9dd38819
PE
1822{
1823 struct sh_mobile_lcdc_chan *ch = info->par;
92e1f9a7
PE
1824 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
1825 unsigned long ldrcntr;
a4aa25f6
LP
1826 unsigned long base_addr_y, base_addr_c;
1827 unsigned long y_offset;
53b50314 1828 unsigned long c_offset;
92e1f9a7 1829
a4aa25f6
LP
1830 if (!ch->format->yuv) {
1831 y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
1832 * ch->format->bpp / 8;
1833 c_offset = 0;
1834 } else {
1835 unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
1836 unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
9dd38819 1837
a4aa25f6
LP
1838 y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
1839 c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
1840 + var->xoffset * 2 / xsub;
1841 }
9dd38819 1842
a4aa25f6
LP
1843 /* If the Y offset hasn't changed, the C offset hasn't either. There's
1844 * nothing to do in that case.
1845 */
1846 if (y_offset == ch->pan_y_offset)
1847 return 0;
9dd38819 1848
92e1f9a7 1849 /* Set the source address for the next refresh */
a4aa25f6
LP
1850 base_addr_y = ch->dma_handle + y_offset;
1851 base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
1852 + c_offset;
53b50314 1853
6e729b41
LP
1854 if (ch->cache)
1855 sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
1856 base_addr_y, base_addr_c,
1857 &base_addr_y, &base_addr_c);
7caa4342 1858
49d79ba2
LP
1859 ch->base_addr_y = base_addr_y;
1860 ch->base_addr_c = base_addr_c;
a4aa25f6 1861 ch->pan_y_offset = y_offset;
7caa4342 1862
49d79ba2 1863 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
58f03d99 1864 if (ch->format->yuv)
49d79ba2 1865 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
53b50314 1866
a4aa25f6 1867 ldrcntr = lcdc_read(priv, _LDRCNTR);
92e1f9a7
PE
1868 if (lcdc_chan_is_sublcd(ch))
1869 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
1870 else
1871 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
1872
92e1f9a7
PE
1873
1874 sh_mobile_lcdc_deferred_io_touch(info);
9dd38819
PE
1875
1876 return 0;
1877}
1878
d7ad3342
LP
1879static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
1880 unsigned long arg)
40331b21 1881{
d7ad3342 1882 struct sh_mobile_lcdc_chan *ch = info->par;
40331b21
PE
1883 int retval;
1884
1885 switch (cmd) {
1886 case FBIO_WAITFORVSYNC:
d7ad3342 1887 retval = sh_mobile_lcdc_wait_for_vsync(ch);
40331b21
PE
1888 break;
1889
1890 default:
1891 retval = -ENOIOCTLCMD;
1892 break;
1893 }
1894 return retval;
1895}
1896
dd210503
GL
1897static void sh_mobile_fb_reconfig(struct fb_info *info)
1898{
1899 struct sh_mobile_lcdc_chan *ch = info->par;
2d04559d
LP
1900 struct fb_var_screeninfo var;
1901 struct fb_videomode mode;
dd210503
GL
1902 struct fb_event event;
1903 int evnt = FB_EVENT_MODE_CHANGE_ALL;
1904
1905 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
1906 /* More framebuffer users are active */
1907 return;
1908
2d04559d 1909 fb_var_to_videomode(&mode, &info->var);
dd210503 1910
2d04559d 1911 if (fb_mode_is_equal(&ch->display.mode, &mode))
dd210503
GL
1912 return;
1913
1914 /* Display has been re-plugged, framebuffer is free now, reconfigure */
2d04559d
LP
1915 var = info->var;
1916 fb_videomode_to_var(&var, &ch->display.mode);
1917 var.width = ch->display.width;
1918 var.height = ch->display.height;
1919 var.activate = FB_ACTIVATE_NOW;
1920
1921 if (fb_set_var(info, &var) < 0)
dd210503
GL
1922 /* Couldn't reconfigure, hopefully, can continue as before */
1923 return;
1924
dd210503
GL
1925 /*
1926 * fb_set_var() calls the notifier change internally, only if
1927 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
1928 * user event, we have to call the chain ourselves.
1929 */
1930 event.info = info;
2d04559d 1931 event.data = &ch->display.mode;
dd210503
GL
1932 fb_notifier_call_chain(evnt, &event);
1933}
1934
1935/*
1936 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
1937 * user == 1, or with console sem held, if user == 0.
1938 */
d7ad3342 1939static int sh_mobile_lcdc_release(struct fb_info *info, int user)
dd210503
GL
1940{
1941 struct sh_mobile_lcdc_chan *ch = info->par;
1942
1943 mutex_lock(&ch->open_lock);
1944 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1945
1946 ch->use_count--;
1947
1948 /* Nothing to reconfigure, when called from fbcon */
1949 if (user) {
ac751efa 1950 console_lock();
dd210503 1951 sh_mobile_fb_reconfig(info);
ac751efa 1952 console_unlock();
dd210503
GL
1953 }
1954
1955 mutex_unlock(&ch->open_lock);
1956
1957 return 0;
1958}
1959
d7ad3342 1960static int sh_mobile_lcdc_open(struct fb_info *info, int user)
dd210503
GL
1961{
1962 struct sh_mobile_lcdc_chan *ch = info->par;
1963
1964 mutex_lock(&ch->open_lock);
1965 ch->use_count++;
1966
1967 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1968 mutex_unlock(&ch->open_lock);
1969
1970 return 0;
1971}
1972
d7ad3342
LP
1973static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
1974 struct fb_info *info)
dd210503
GL
1975{
1976 struct sh_mobile_lcdc_chan *ch = info->par;
417d4827 1977 struct sh_mobile_lcdc_priv *p = ch->lcdc;
03862194
LP
1978 unsigned int best_dist = (unsigned int)-1;
1979 unsigned int best_xres = 0;
1980 unsigned int best_yres = 0;
1981 unsigned int i;
c5deac3c 1982 int ret;
03862194
LP
1983
1984 /* If board code provides us with a list of available modes, make sure
1985 * we use one of them. Find the mode closest to the requested one. The
1986 * distance between two modes is defined as the size of the
1987 * non-overlapping parts of the two rectangles.
1988 */
b5ef967d
LP
1989 for (i = 0; i < ch->cfg->num_modes; ++i) {
1990 const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
03862194
LP
1991 unsigned int dist;
1992
1993 /* We can only round up. */
1994 if (var->xres > mode->xres || var->yres > mode->yres)
1995 continue;
1996
1997 dist = var->xres * var->yres + mode->xres * mode->yres
1998 - 2 * min(var->xres, mode->xres)
1999 * min(var->yres, mode->yres);
2000
2001 if (dist < best_dist) {
2002 best_xres = mode->xres;
2003 best_yres = mode->yres;
2004 best_dist = dist;
2005 }
dd210503 2006 }
417d4827 2007
03862194 2008 /* If no available mode can be used, return an error. */
b5ef967d 2009 if (ch->cfg->num_modes != 0) {
03862194
LP
2010 if (best_dist == (unsigned int)-1)
2011 return -EINVAL;
2012
2013 var->xres = best_xres;
2014 var->yres = best_yres;
2015 }
2016
c5deac3c
LP
2017 ret = __sh_mobile_lcdc_check_var(var, info);
2018 if (ret < 0)
2019 return ret;
03862194 2020
edd153a3
LP
2021 /* only accept the forced_fourcc for dual channel configurations */
2022 if (p->forced_fourcc &&
2023 p->forced_fourcc != sh_mobile_format_fourcc(var))
417d4827 2024 return -EINVAL;
417d4827 2025
dd210503
GL
2026 return 0;
2027}
40331b21 2028
d7ad3342 2029static int sh_mobile_lcdc_set_par(struct fb_info *info)
ed5bebf2
LP
2030{
2031 struct sh_mobile_lcdc_chan *ch = info->par;
2032 int ret;
2033
2034 sh_mobile_lcdc_stop(ch->lcdc);
91fba48d 2035
fc9e78e6 2036 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
58f03d99
LP
2037 ch->colorspace = info->var.colorspace;
2038
2039 ch->xres = info->var.xres;
2040 ch->xres_virtual = info->var.xres_virtual;
2041 ch->yres = info->var.yres;
2042 ch->yres_virtual = info->var.yres_virtual;
2043
2044 if (ch->format->yuv)
16ca21c9 2045 ch->pitch = info->var.xres_virtual;
58f03d99 2046 else
16ca21c9 2047 ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
fc9e78e6 2048
ed5bebf2 2049 ret = sh_mobile_lcdc_start(ch->lcdc);
58f03d99 2050 if (ret < 0)
ed5bebf2 2051 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
58f03d99
LP
2052
2053 info->fix.line_length = ch->pitch;
ed5bebf2 2054
edd153a3
LP
2055 if (sh_mobile_format_is_fourcc(&info->var)) {
2056 info->fix.type = FB_TYPE_FOURCC;
2057 info->fix.visual = FB_VISUAL_FOURCC;
2058 } else {
2059 info->fix.type = FB_TYPE_PACKED_PIXELS;
2060 info->fix.visual = FB_VISUAL_TRUECOLOR;
2061 }
2062
ed5bebf2
LP
2063 return ret;
2064}
2065
8857b9aa
AC
2066/*
2067 * Screen blanking. Behavior is as follows:
2068 * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
2069 * FB_BLANK_NORMAL: screen blanked, clocks enabled
2070 * FB_BLANK_VSYNC,
2071 * FB_BLANK_HSYNC,
2072 * FB_BLANK_POWEROFF: screen blanked, clocks disabled
2073 */
2074static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
2075{
2076 struct sh_mobile_lcdc_chan *ch = info->par;
2077 struct sh_mobile_lcdc_priv *p = ch->lcdc;
2078
2079 /* blank the screen? */
2080 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
2081 struct fb_fillrect rect = {
58f03d99
LP
2082 .width = ch->xres,
2083 .height = ch->yres,
8857b9aa
AC
2084 };
2085 sh_mobile_lcdc_fillrect(info, &rect);
2086 }
2087 /* turn clocks on? */
2088 if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
2089 sh_mobile_lcdc_clk_on(p);
2090 }
2091 /* turn clocks off? */
2092 if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
2093 /* make sure the screen is updated with the black fill before
2094 * switching the clocks off. one vsync is not enough since
2095 * blanking may occur in the middle of a refresh. deferred io
2096 * mode will reenable the clocks and update the screen in time,
2097 * so it does not need this. */
2098 if (!info->fbdefio) {
d7ad3342
LP
2099 sh_mobile_lcdc_wait_for_vsync(ch);
2100 sh_mobile_lcdc_wait_for_vsync(ch);
8857b9aa
AC
2101 }
2102 sh_mobile_lcdc_clk_off(p);
2103 }
2104
2105 ch->blank_status = blank;
2106 return 0;
2107}
2108
bf10a537
HE
2109static int
2110sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
2111{
2112 struct sh_mobile_lcdc_chan *ch = info->par;
2113
2114 return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
2115 ch->dma_handle, ch->fb_size);
2116}
2117
cfb4f5d1 2118static struct fb_ops sh_mobile_lcdc_ops = {
9dd38819 2119 .owner = THIS_MODULE,
cfb4f5d1 2120 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
2540c111
MD
2121 .fb_read = fb_sys_read,
2122 .fb_write = fb_sys_write,
8564557a
MD
2123 .fb_fillrect = sh_mobile_lcdc_fillrect,
2124 .fb_copyarea = sh_mobile_lcdc_copyarea,
2125 .fb_imageblit = sh_mobile_lcdc_imageblit,
8857b9aa 2126 .fb_blank = sh_mobile_lcdc_blank,
d7ad3342
LP
2127 .fb_pan_display = sh_mobile_lcdc_pan,
2128 .fb_ioctl = sh_mobile_lcdc_ioctl,
2129 .fb_open = sh_mobile_lcdc_open,
2130 .fb_release = sh_mobile_lcdc_release,
2131 .fb_check_var = sh_mobile_lcdc_check_var,
2132 .fb_set_par = sh_mobile_lcdc_set_par,
bf10a537 2133 .fb_mmap = sh_mobile_lcdc_mmap,
cfb4f5d1
MD
2134};
2135
a67f379d
LP
2136static void
2137sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
2138{
2139 if (ch->info && ch->info->dev)
2140 unregister_framebuffer(ch->info);
2141}
2142
48c68c4f 2143static int
a67f379d
LP
2144sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
2145{
2146 struct fb_info *info = ch->info;
2147 int ret;
2148
2149 if (info->fbdefio) {
2150 ch->sglist = vmalloc(sizeof(struct scatterlist) *
2151 ch->fb_size >> PAGE_SHIFT);
2152 if (!ch->sglist) {
2153 dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
2154 return -ENOMEM;
2155 }
2156 }
2157
2158 info->bl_dev = ch->bl;
2159
2160 ret = register_framebuffer(info);
2161 if (ret < 0)
2162 return ret;
2163
2164 dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
b5ef967d 2165 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
a67f379d
LP
2166 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
2167 info->var.bits_per_pixel);
2168
2169 /* deferred io mode: disable clock to save power */
2170 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
2171 sh_mobile_lcdc_clk_off(ch->lcdc);
2172
2173 return ret;
2174}
2175
2176static void
2177sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
2178{
2179 struct fb_info *info = ch->info;
2180
2181 if (!info || !info->device)
2182 return;
2183
2184 if (ch->sglist)
2185 vfree(ch->sglist);
2186
2187 fb_dealloc_cmap(&info->cmap);
2188 framebuffer_release(info);
2189}
2190
48c68c4f 2191static int
a67f379d 2192sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
352d6138 2193 const struct fb_videomode *modes,
a67f379d
LP
2194 unsigned int num_modes)
2195{
2196 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
2197 struct fb_var_screeninfo *var;
2198 struct fb_info *info;
2199 int ret;
2200
2201 /* Allocate and initialize the frame buffer device. Create the modes
2202 * list and allocate the color map.
2203 */
2204 info = framebuffer_alloc(0, priv->dev);
2205 if (info == NULL) {
2206 dev_err(priv->dev, "unable to allocate fb_info\n");
2207 return -ENOMEM;
2208 }
2209
2210 ch->info = info;
2211
2212 info->flags = FBINFO_FLAG_DEFAULT;
2213 info->fbops = &sh_mobile_lcdc_ops;
2214 info->device = priv->dev;
2215 info->screen_base = ch->fb_mem;
2216 info->pseudo_palette = &ch->pseudo_palette;
2217 info->par = ch;
2218
352d6138 2219 fb_videomode_to_modelist(modes, num_modes, &info->modelist);
a67f379d
LP
2220
2221 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
2222 if (ret < 0) {
2223 dev_err(priv->dev, "unable to allocate cmap\n");
2224 return ret;
2225 }
2226
2227 /* Initialize fixed screen information. Restrict pan to 2 lines steps
2228 * for NV12 and NV21.
2229 */
2230 info->fix = sh_mobile_lcdc_fix;
2231 info->fix.smem_start = ch->dma_handle;
2232 info->fix.smem_len = ch->fb_size;
58f03d99
LP
2233 info->fix.line_length = ch->pitch;
2234
2235 if (ch->format->yuv)
2236 info->fix.visual = FB_VISUAL_FOURCC;
2237 else
2238 info->fix.visual = FB_VISUAL_TRUECOLOR;
2239
15dede88 2240 switch (ch->format->fourcc) {
15dede88
LP
2241 case V4L2_PIX_FMT_NV12:
2242 case V4L2_PIX_FMT_NV21:
ac33a207
LP
2243 info->fix.ypanstep = 2;
2244 case V4L2_PIX_FMT_NV16:
2245 case V4L2_PIX_FMT_NV61:
15dede88
LP
2246 info->fix.xpanstep = 2;
2247 }
a67f379d
LP
2248
2249 /* Initialize variable screen information using the first mode as
bd5f2c69 2250 * default.
a67f379d
LP
2251 */
2252 var = &info->var;
352d6138 2253 fb_videomode_to_var(var, modes);
856e8dfe
LP
2254 var->width = ch->display.width;
2255 var->height = ch->display.height;
bd5f2c69
LP
2256 var->xres_virtual = ch->xres_virtual;
2257 var->yres_virtual = ch->yres_virtual;
a67f379d
LP
2258 var->activate = FB_ACTIVATE_NOW;
2259
2260 /* Use the legacy API by default for RGB formats, and the FOURCC API
2261 * for YUV formats.
2262 */
2263 if (!ch->format->yuv)
2264 var->bits_per_pixel = ch->format->bpp;
2265 else
2266 var->grayscale = ch->format->fourcc;
2267
d7ad3342 2268 ret = sh_mobile_lcdc_check_var(var, info);
a67f379d
LP
2269 if (ret)
2270 return ret;
2271
a67f379d
LP
2272 return 0;
2273}
2274
f1f60b5f
LP
2275/* -----------------------------------------------------------------------------
2276 * Backlight
2277 */
2278
3b0fd9d7
AC
2279static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
2280{
2281 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
3b0fd9d7
AC
2282 int brightness = bdev->props.brightness;
2283
2284 if (bdev->props.power != FB_BLANK_UNBLANK ||
2285 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
2286 brightness = 0;
2287
656d4f33 2288 ch->bl_brightness = brightness;
b5ef967d 2289 return ch->cfg->bl_info.set_brightness(brightness);
3b0fd9d7
AC
2290}
2291
2292static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
2293{
2294 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
3b0fd9d7 2295
656d4f33 2296 return ch->bl_brightness;
3b0fd9d7
AC
2297}
2298
2299static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
2300 struct fb_info *info)
2301{
2302 return (info->bl_dev == bdev);
2303}
2304
2305static struct backlight_ops sh_mobile_lcdc_bl_ops = {
2306 .options = BL_CORE_SUSPENDRESUME,
2307 .update_status = sh_mobile_lcdc_update_bl,
2308 .get_brightness = sh_mobile_lcdc_get_brightness,
2309 .check_fb = sh_mobile_lcdc_check_fb,
2310};
2311
2312static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
2313 struct sh_mobile_lcdc_chan *ch)
2314{
2315 struct backlight_device *bl;
2316
b5ef967d 2317 bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
3b0fd9d7 2318 &sh_mobile_lcdc_bl_ops, NULL);
beee1f20
DC
2319 if (IS_ERR(bl)) {
2320 dev_err(parent, "unable to register backlight device: %ld\n",
2321 PTR_ERR(bl));
3b0fd9d7
AC
2322 return NULL;
2323 }
2324
b5ef967d 2325 bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
3b0fd9d7
AC
2326 bl->props.brightness = bl->props.max_brightness;
2327 backlight_update_status(bl);
2328
2329 return bl;
2330}
2331
2332static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
2333{
2334 backlight_device_unregister(bdev);
2335}
2336
f1f60b5f
LP
2337/* -----------------------------------------------------------------------------
2338 * Power management
2339 */
2340
2feb075a
MD
2341static int sh_mobile_lcdc_suspend(struct device *dev)
2342{
2343 struct platform_device *pdev = to_platform_device(dev);
2344
2345 sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
2346 return 0;
2347}
2348
2349static int sh_mobile_lcdc_resume(struct device *dev)
2350{
2351 struct platform_device *pdev = to_platform_device(dev);
2352
2353 return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
2354}
2355
0246c471
MD
2356static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
2357{
2358 struct platform_device *pdev = to_platform_device(dev);
2427bb24 2359 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
0246c471
MD
2360
2361 /* turn off LCDC hardware */
2427bb24
LP
2362 lcdc_write(priv, _LDCNT1R, 0);
2363
0246c471
MD
2364 return 0;
2365}
2366
2367static int sh_mobile_lcdc_runtime_resume(struct device *dev)
2368{
2369 struct platform_device *pdev = to_platform_device(dev);
2427bb24 2370 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
0246c471 2371
2427bb24 2372 __sh_mobile_lcdc_start(priv);
0246c471
MD
2373
2374 return 0;
2375}
2376
47145210 2377static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
2feb075a
MD
2378 .suspend = sh_mobile_lcdc_suspend,
2379 .resume = sh_mobile_lcdc_resume,
0246c471
MD
2380 .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
2381 .runtime_resume = sh_mobile_lcdc_runtime_resume,
2feb075a
MD
2382};
2383
f1f60b5f
LP
2384/* -----------------------------------------------------------------------------
2385 * Framebuffer notifier
2386 */
2387
6de9edd5 2388/* locking: called with info->lock held */
6011bdea
GL
2389static int sh_mobile_lcdc_notify(struct notifier_block *nb,
2390 unsigned long action, void *data)
2391{
2392 struct fb_event *event = data;
2393 struct fb_info *info = event->info;
2394 struct sh_mobile_lcdc_chan *ch = info->par;
6011bdea
GL
2395
2396 if (&ch->lcdc->notifier != nb)
baf16374 2397 return NOTIFY_DONE;
6011bdea
GL
2398
2399 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
2400 __func__, action, event->data);
2401
2402 switch(action) {
2403 case FB_EVENT_SUSPEND:
37c5dcc2 2404 sh_mobile_lcdc_display_off(ch);
afe417c0 2405 sh_mobile_lcdc_stop(ch->lcdc);
6011bdea
GL
2406 break;
2407 case FB_EVENT_RESUME:
dd210503
GL
2408 mutex_lock(&ch->open_lock);
2409 sh_mobile_fb_reconfig(info);
2410 mutex_unlock(&ch->open_lock);
6011bdea 2411
37c5dcc2 2412 sh_mobile_lcdc_display_on(ch);
ebe5e12d 2413 sh_mobile_lcdc_start(ch->lcdc);
6011bdea
GL
2414 }
2415
baf16374 2416 return NOTIFY_OK;
6011bdea
GL
2417}
2418
f1f60b5f
LP
2419/* -----------------------------------------------------------------------------
2420 * Probe/remove and driver init/exit
2421 */
2422
48c68c4f 2423static const struct fb_videomode default_720p = {
f1f60b5f
LP
2424 .name = "HDMI 720p",
2425 .xres = 1280,
2426 .yres = 720,
2427
2428 .left_margin = 220,
2429 .right_margin = 110,
2430 .hsync_len = 40,
2431
2432 .upper_margin = 20,
2433 .lower_margin = 5,
2434 .vsync_len = 5,
2435
2436 .pixclock = 13468,
2437 .refresh = 60,
2438 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
2439};
2440
b4bee692
LP
2441static int sh_mobile_lcdc_remove(struct platform_device *pdev)
2442{
2443 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
c5deac3c 2444 unsigned int i;
b4bee692
LP
2445
2446 fb_unregister_client(&priv->notifier);
2447
c5deac3c
LP
2448 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
2449 sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
b4bee692 2450 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
a67f379d 2451 sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
b4bee692
LP
2452
2453 sh_mobile_lcdc_stop(priv);
2454
c5deac3c
LP
2455 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
2456 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2457
2458 sh_mobile_lcdc_overlay_fb_cleanup(ovl);
2459
2460 if (ovl->fb_mem)
2461 dma_free_coherent(&pdev->dev, ovl->fb_size,
2462 ovl->fb_mem, ovl->dma_handle);
2463 }
2464
b4bee692 2465 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
9a2985e7 2466 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
b4bee692 2467
e34d0bbb
LP
2468 if (ch->tx_dev) {
2469 ch->tx_dev->lcdc = NULL;
b5ef967d 2470 module_put(ch->cfg->tx_dev->dev.driver->owner);
e34d0bbb 2471 }
9a2985e7 2472
a67f379d 2473 sh_mobile_lcdc_channel_fb_cleanup(ch);
b4bee692 2474
a67f379d
LP
2475 if (ch->fb_mem)
2476 dma_free_coherent(&pdev->dev, ch->fb_size,
2477 ch->fb_mem, ch->dma_handle);
b4bee692
LP
2478 }
2479
2480 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
0c75c4e0
LP
2481 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
2482
2483 if (ch->bl)
2484 sh_mobile_lcdc_bl_remove(ch->bl);
2485 mutex_destroy(&ch->open_lock);
b4bee692
LP
2486 }
2487
4774c12a
LP
2488 if (priv->dot_clk) {
2489 pm_runtime_disable(&pdev->dev);
b4bee692 2490 clk_put(priv->dot_clk);
4774c12a 2491 }
b4bee692
LP
2492
2493 if (priv->base)
2494 iounmap(priv->base);
2495
2496 if (priv->irq)
2497 free_irq(priv->irq, priv);
2498 kfree(priv);
2499 return 0;
2500}
cfb4f5d1 2501
48c68c4f 2502static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
f1f60b5f 2503{
b5ef967d 2504 int interface_type = ch->cfg->interface_type;
f1f60b5f
LP
2505
2506 switch (interface_type) {
2507 case RGB8:
2508 case RGB9:
2509 case RGB12A:
2510 case RGB12B:
2511 case RGB16:
2512 case RGB18:
2513 case RGB24:
2514 case SYS8A:
2515 case SYS8B:
2516 case SYS8C:
2517 case SYS8D:
2518 case SYS9:
2519 case SYS12:
2520 case SYS16A:
2521 case SYS16B:
2522 case SYS16C:
2523 case SYS18:
2524 case SYS24:
2525 break;
2526 default:
2527 return -EINVAL;
2528 }
2529
2530 /* SUBLCD only supports SYS interface */
2531 if (lcdc_chan_is_sublcd(ch)) {
2532 if (!(interface_type & LDMT1R_IFM))
2533 return -EINVAL;
2534
2535 interface_type &= ~LDMT1R_IFM;
2536 }
2537
2538 ch->ldmt1r_value = interface_type;
2539 return 0;
2540}
2541
48c68c4f 2542static int
0707330b 2543sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
c5deac3c
LP
2544{
2545 const struct sh_mobile_lcdc_format_info *format;
0707330b 2546 struct device *dev = ovl->channel->lcdc->dev;
c5deac3c
LP
2547 int ret;
2548
2549 if (ovl->cfg->fourcc == 0)
2550 return 0;
2551
2552 /* Validate the format. */
2553 format = sh_mobile_format_info(ovl->cfg->fourcc);
2554 if (format == NULL) {
0707330b 2555 dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
c5deac3c
LP
2556 return -EINVAL;
2557 }
2558
2559 ovl->enabled = false;
2560 ovl->mode = LCDC_OVERLAY_BLEND;
2561 ovl->alpha = 255;
2562 ovl->rop3 = 0;
2563 ovl->pos_x = 0;
2564 ovl->pos_y = 0;
2565
2566 /* The default Y virtual resolution is twice the panel size to allow for
2567 * double-buffering.
2568 */
2569 ovl->format = format;
2570 ovl->xres = ovl->cfg->max_xres;
2571 ovl->xres_virtual = ovl->xres;
2572 ovl->yres = ovl->cfg->max_yres;
2573 ovl->yres_virtual = ovl->yres * 2;
2574
2575 if (!format->yuv)
16ca21c9 2576 ovl->pitch = ovl->xres_virtual * format->bpp / 8;
c5deac3c 2577 else
16ca21c9 2578 ovl->pitch = ovl->xres_virtual;
c5deac3c
LP
2579
2580 /* Allocate frame buffer memory. */
2581 ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
2582 * format->bpp / 8 * 2;
0707330b
LP
2583 ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
2584 GFP_KERNEL);
c5deac3c 2585 if (!ovl->fb_mem) {
0707330b 2586 dev_err(dev, "unable to allocate buffer\n");
c5deac3c
LP
2587 return -ENOMEM;
2588 }
2589
2590 ret = sh_mobile_lcdc_overlay_fb_init(ovl);
2591 if (ret < 0)
2592 return ret;
2593
2594 return 0;
2595}
2596
48c68c4f 2597static int
0707330b 2598sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
cfb4f5d1 2599{
105784bb 2600 const struct sh_mobile_lcdc_format_info *format;
b5ef967d 2601 const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
0707330b 2602 struct device *dev = ch->lcdc->dev;
3ce05599
LP
2603 const struct fb_videomode *max_mode;
2604 const struct fb_videomode *mode;
a67f379d 2605 unsigned int num_modes;
3ce05599 2606 unsigned int max_size;
a67f379d 2607 unsigned int i;
3ce05599 2608
a67472ad 2609 mutex_init(&ch->open_lock);
ecd29947 2610 ch->notify = sh_mobile_lcdc_display_notify;
a67472ad 2611
105784bb
LP
2612 /* Validate the format. */
2613 format = sh_mobile_format_info(cfg->fourcc);
2614 if (format == NULL) {
0707330b 2615 dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
105784bb
LP
2616 return -EINVAL;
2617 }
2618
3ce05599
LP
2619 /* Iterate through the modes to validate them and find the highest
2620 * resolution.
2621 */
2622 max_mode = NULL;
2623 max_size = 0;
2624
93ff2598 2625 for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
3ce05599
LP
2626 unsigned int size = mode->yres * mode->xres;
2627
edd153a3
LP
2628 /* NV12/NV21 buffers must have even number of lines */
2629 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
2630 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
0707330b 2631 dev_err(dev, "yres must be multiple of 2 for "
0a7f17aa 2632 "YCbCr420 mode.\n");
3ce05599
LP
2633 return -EINVAL;
2634 }
2635
2636 if (size > max_size) {
2637 max_mode = mode;
2638 max_size = size;
2639 }
2640 }
2641
2642 if (!max_size)
2643 max_size = MAX_XRES * MAX_YRES;
2644 else
0707330b 2645 dev_dbg(dev, "Found largest videomode %ux%u\n",
3ce05599
LP
2646 max_mode->xres, max_mode->yres);
2647
93ff2598 2648 if (cfg->lcd_modes == NULL) {
3ce05599 2649 mode = &default_720p;
93ff2598 2650 num_modes = 1;
3ce05599 2651 } else {
93ff2598
LP
2652 mode = cfg->lcd_modes;
2653 num_modes = cfg->num_modes;
3ce05599
LP
2654 }
2655
bd5f2c69
LP
2656 /* Use the first mode as default. The default Y virtual resolution is
2657 * twice the panel size to allow for double-buffering.
2658 */
58f03d99
LP
2659 ch->format = format;
2660 ch->xres = mode->xres;
2661 ch->xres_virtual = mode->xres;
2662 ch->yres = mode->yres;
2663 ch->yres_virtual = mode->yres * 2;
2664
2665 if (!format->yuv) {
2666 ch->colorspace = V4L2_COLORSPACE_SRGB;
16ca21c9 2667 ch->pitch = ch->xres_virtual * format->bpp / 8;
58f03d99
LP
2668 } else {
2669 ch->colorspace = V4L2_COLORSPACE_REC709;
16ca21c9 2670 ch->pitch = ch->xres_virtual;
58f03d99
LP
2671 }
2672
a67f379d
LP
2673 ch->display.width = cfg->panel_cfg.width;
2674 ch->display.height = cfg->panel_cfg.height;
2675 ch->display.mode = *mode;
2676
2677 /* Allocate frame buffer memory. */
2678 ch->fb_size = max_size * format->bpp / 8 * 2;
0707330b 2679 ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
a67f379d
LP
2680 GFP_KERNEL);
2681 if (ch->fb_mem == NULL) {
0707330b 2682 dev_err(dev, "unable to allocate buffer\n");
a67f379d
LP
2683 return -ENOMEM;
2684 }
3ce05599 2685
13f80eea
LP
2686 /* Initialize the transmitter device if present. */
2687 if (cfg->tx_dev) {
2688 if (!cfg->tx_dev->dev.driver ||
2689 !try_module_get(cfg->tx_dev->dev.driver->owner)) {
0707330b 2690 dev_warn(dev, "unable to get transmitter device\n");
13f80eea
LP
2691 return -EINVAL;
2692 }
2693 ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
2694 ch->tx_dev->lcdc = ch;
2695 ch->tx_dev->def_mode = *mode;
2696 }
2697
a67f379d 2698 return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
3ce05599
LP
2699}
2700
48c68c4f 2701static int sh_mobile_lcdc_probe(struct platform_device *pdev)
3ce05599 2702{
01ac25b5 2703 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
3ce05599 2704 struct sh_mobile_lcdc_priv *priv;
cfb4f5d1 2705 struct resource *res;
3ce05599 2706 int num_channels;
cfb4f5d1 2707 int error;
3ce05599 2708 int i;
cfb4f5d1 2709
01ac25b5 2710 if (!pdata) {
cfb4f5d1 2711 dev_err(&pdev->dev, "no platform data defined\n");
8bed9055 2712 return -EINVAL;
cfb4f5d1
MD
2713 }
2714
2715 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8564557a
MD
2716 i = platform_get_irq(pdev, 0);
2717 if (!res || i < 0) {
2718 dev_err(&pdev->dev, "cannot get platform resources\n");
8bed9055 2719 return -ENOENT;
cfb4f5d1
MD
2720 }
2721
2722 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
2723 if (!priv) {
2724 dev_err(&pdev->dev, "cannot allocate device data\n");
8bed9055 2725 return -ENOMEM;
cfb4f5d1
MD
2726 }
2727
4774c12a
LP
2728 priv->dev = &pdev->dev;
2729 priv->meram_dev = pdata->meram_dev;
8bed9055
GL
2730 platform_set_drvdata(pdev, priv);
2731
f8798ccb 2732 error = request_irq(i, sh_mobile_lcdc_irq, 0,
7ad33e74 2733 dev_name(&pdev->dev), priv);
8564557a
MD
2734 if (error) {
2735 dev_err(&pdev->dev, "unable to request irq\n");
2736 goto err1;
2737 }
2738
2739 priv->irq = i;
5ef6b505 2740 atomic_set(&priv->hw_usecnt, -1);
cfb4f5d1 2741
3ce05599
LP
2742 for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
2743 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
cfb4f5d1 2744
01ac25b5 2745 ch->lcdc = priv;
b5ef967d 2746 ch->cfg = &pdata->ch[i];
cfb4f5d1 2747
01ac25b5 2748 error = sh_mobile_lcdc_check_interface(ch);
cfb4f5d1
MD
2749 if (error) {
2750 dev_err(&pdev->dev, "unsupported interface type\n");
2751 goto err1;
2752 }
01ac25b5
GL
2753 init_waitqueue_head(&ch->frame_end_wait);
2754 init_completion(&ch->vsync_completion);
cfb4f5d1 2755
3b0fd9d7 2756 /* probe the backlight is there is one defined */
b5ef967d 2757 if (ch->cfg->bl_info.max_brightness)
3b0fd9d7
AC
2758 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
2759
cfb4f5d1
MD
2760 switch (pdata->ch[i].chan) {
2761 case LCDC_CHAN_MAINLCD:
ce1c0b08 2762 ch->enabled = LDCNT2R_ME;
01ac25b5 2763 ch->reg_offs = lcdc_offs_mainlcd;
3ce05599 2764 num_channels++;
cfb4f5d1
MD
2765 break;
2766 case LCDC_CHAN_SUBLCD:
ce1c0b08 2767 ch->enabled = LDCNT2R_SE;
01ac25b5 2768 ch->reg_offs = lcdc_offs_sublcd;
3ce05599 2769 num_channels++;
cfb4f5d1
MD
2770 break;
2771 }
2772 }
2773
3ce05599 2774 if (!num_channels) {
cfb4f5d1
MD
2775 dev_err(&pdev->dev, "no channels defined\n");
2776 error = -EINVAL;
2777 goto err1;
2778 }
2779
edd153a3 2780 /* for dual channel LCDC (MAIN + SUB) force shared format setting */
3ce05599 2781 if (num_channels == 2)
edd153a3 2782 priv->forced_fourcc = pdata->ch[0].fourcc;
417d4827 2783
dba6f385
GL
2784 priv->base = ioremap_nocache(res->start, resource_size(res));
2785 if (!priv->base)
2786 goto err1;
2787
0a7f17aa 2788 error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
cfb4f5d1
MD
2789 if (error) {
2790 dev_err(&pdev->dev, "unable to setup clocks\n");
2791 goto err1;
2792 }
2793
4774c12a
LP
2794 /* Enable runtime PM. */
2795 pm_runtime_enable(&pdev->dev);
7caa4342 2796
3ce05599 2797 for (i = 0; i < num_channels; i++) {
0707330b 2798 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
c44f9f76 2799
0707330b 2800 error = sh_mobile_lcdc_channel_init(ch);
cfb4f5d1 2801 if (error)
3ce05599 2802 goto err1;
cfb4f5d1
MD
2803 }
2804
c5deac3c
LP
2805 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
2806 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2807
2808 ovl->cfg = &pdata->overlays[i];
2809 ovl->channel = &priv->ch[0];
2810
0707330b 2811 error = sh_mobile_lcdc_overlay_init(ovl);
c5deac3c
LP
2812 if (error)
2813 goto err1;
2814 }
2815
cfb4f5d1
MD
2816 error = sh_mobile_lcdc_start(priv);
2817 if (error) {
2818 dev_err(&pdev->dev, "unable to start hardware\n");
2819 goto err1;
2820 }
2821
3ce05599 2822 for (i = 0; i < num_channels; i++) {
1c6a307a 2823 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1c6a307a 2824
a67f379d
LP
2825 error = sh_mobile_lcdc_channel_fb_register(ch);
2826 if (error)
cfb4f5d1 2827 goto err1;
cfb4f5d1
MD
2828 }
2829
c5deac3c
LP
2830 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
2831 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2832
2833 error = sh_mobile_lcdc_overlay_fb_register(ovl);
2834 if (error)
2835 goto err1;
2836 }
2837
6011bdea
GL
2838 /* Failure ignored */
2839 priv->notifier.notifier_call = sh_mobile_lcdc_notify;
2840 fb_register_client(&priv->notifier);
2841
cfb4f5d1 2842 return 0;
8bed9055 2843err1:
cfb4f5d1 2844 sh_mobile_lcdc_remove(pdev);
8bed9055 2845
cfb4f5d1
MD
2846 return error;
2847}
2848
cfb4f5d1
MD
2849static struct platform_driver sh_mobile_lcdc_driver = {
2850 .driver = {
2851 .name = "sh_mobile_lcdc_fb",
2852 .owner = THIS_MODULE,
2feb075a 2853 .pm = &sh_mobile_lcdc_dev_pm_ops,
cfb4f5d1
MD
2854 },
2855 .probe = sh_mobile_lcdc_probe,
2856 .remove = sh_mobile_lcdc_remove,
2857};
2858
4277f2c4 2859module_platform_driver(sh_mobile_lcdc_driver);
cfb4f5d1
MD
2860
2861MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
2862MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
2863MODULE_LICENSE("GPL v2");