Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rfbi.c
Go to the documentation of this file.
1 /*
2  * linux/drivers/video/omap2/dss/rfbi.c
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Author: Tomi Valkeinen <[email protected]>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #define DSS_SUBSYS_NAME "RFBI"
24 
25 #include <linux/kernel.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/export.h>
28 #include <linux/vmalloc.h>
29 #include <linux/clk.h>
30 #include <linux/io.h>
31 #include <linux/delay.h>
32 #include <linux/kfifo.h>
33 #include <linux/ktime.h>
34 #include <linux/hrtimer.h>
35 #include <linux/seq_file.h>
36 #include <linux/semaphore.h>
37 #include <linux/platform_device.h>
38 #include <linux/pm_runtime.h>
39 
40 #include <video/omapdss.h>
41 #include "dss.h"
42 
43 struct rfbi_reg { u16 idx; };
44 
45 #define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
46 
47 #define RFBI_REVISION RFBI_REG(0x0000)
48 #define RFBI_SYSCONFIG RFBI_REG(0x0010)
49 #define RFBI_SYSSTATUS RFBI_REG(0x0014)
50 #define RFBI_CONTROL RFBI_REG(0x0040)
51 #define RFBI_PIXEL_CNT RFBI_REG(0x0044)
52 #define RFBI_LINE_NUMBER RFBI_REG(0x0048)
53 #define RFBI_CMD RFBI_REG(0x004c)
54 #define RFBI_PARAM RFBI_REG(0x0050)
55 #define RFBI_DATA RFBI_REG(0x0054)
56 #define RFBI_READ RFBI_REG(0x0058)
57 #define RFBI_STATUS RFBI_REG(0x005c)
58 
59 #define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
60 #define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
61 #define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
62 #define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
63 #define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
64 #define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
65 
66 #define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
67 #define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
68 
69 #define REG_FLD_MOD(idx, val, start, end) \
70  rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
71 
77 };
78 
84 };
85 
91 };
92 
93 static int rfbi_convert_timings(struct rfbi_timings *t);
94 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
95 
96 static struct {
98  void __iomem *base;
99 
100  unsigned long l4_khz;
101 
104 
107 
110 
112 
114 
119 
121 } rfbi;
122 
123 static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
124 {
125  __raw_writel(val, rfbi.base + idx.idx);
126 }
127 
128 static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
129 {
130  return __raw_readl(rfbi.base + idx.idx);
131 }
132 
133 static int rfbi_runtime_get(void)
134 {
135  int r;
136 
137  DSSDBG("rfbi_runtime_get\n");
138 
139  r = pm_runtime_get_sync(&rfbi.pdev->dev);
140  WARN_ON(r < 0);
141  return r < 0 ? r : 0;
142 }
143 
144 static void rfbi_runtime_put(void)
145 {
146  int r;
147 
148  DSSDBG("rfbi_runtime_put\n");
149 
150  r = pm_runtime_put_sync(&rfbi.pdev->dev);
151  WARN_ON(r < 0 && r != -ENOSYS);
152 }
153 
154 void rfbi_bus_lock(void)
155 {
156  down(&rfbi.bus_lock);
157 }
159 
160 void rfbi_bus_unlock(void)
161 {
162  up(&rfbi.bus_lock);
163 }
165 
166 void omap_rfbi_write_command(const void *buf, u32 len)
167 {
168  switch (rfbi.parallelmode) {
170  {
171  const u8 *b = buf;
172  for (; len; len--)
173  rfbi_write_reg(RFBI_CMD, *b++);
174  break;
175  }
176 
178  {
179  const u16 *w = buf;
180  BUG_ON(len & 1);
181  for (; len; len -= 2)
182  rfbi_write_reg(RFBI_CMD, *w++);
183  break;
184  }
185 
188  default:
189  BUG();
190  }
191 }
193 
194 void omap_rfbi_read_data(void *buf, u32 len)
195 {
196  switch (rfbi.parallelmode) {
198  {
199  u8 *b = buf;
200  for (; len; len--) {
201  rfbi_write_reg(RFBI_READ, 0);
202  *b++ = rfbi_read_reg(RFBI_READ);
203  }
204  break;
205  }
206 
208  {
209  u16 *w = buf;
210  BUG_ON(len & ~1);
211  for (; len; len -= 2) {
212  rfbi_write_reg(RFBI_READ, 0);
213  *w++ = rfbi_read_reg(RFBI_READ);
214  }
215  break;
216  }
217 
220  default:
221  BUG();
222  }
223 }
225 
226 void omap_rfbi_write_data(const void *buf, u32 len)
227 {
228  switch (rfbi.parallelmode) {
230  {
231  const u8 *b = buf;
232  for (; len; len--)
233  rfbi_write_reg(RFBI_PARAM, *b++);
234  break;
235  }
236 
238  {
239  const u16 *w = buf;
240  BUG_ON(len & 1);
241  for (; len; len -= 2)
242  rfbi_write_reg(RFBI_PARAM, *w++);
243  break;
244  }
245 
248  default:
249  BUG();
250 
251  }
252 }
254 
255 void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
256  u16 x, u16 y,
257  u16 w, u16 h)
258 {
259  int start_offset = scr_width * y + x;
260  int horiz_offset = scr_width - w;
261  int i;
262 
263  if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
264  rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
265  const u16 __iomem *pd = buf;
266  pd += start_offset;
267 
268  for (; h; --h) {
269  for (i = 0; i < w; ++i) {
270  const u8 __iomem *b = (const u8 __iomem *)pd;
271  rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
272  rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
273  ++pd;
274  }
275  pd += horiz_offset;
276  }
277  } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
278  rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
279  const u32 __iomem *pd = buf;
280  pd += start_offset;
281 
282  for (; h; --h) {
283  for (i = 0; i < w; ++i) {
284  const u8 __iomem *b = (const u8 __iomem *)pd;
285  rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
286  rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
287  rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
288  ++pd;
289  }
290  pd += horiz_offset;
291  }
292  } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
293  rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
294  const u16 __iomem *pd = buf;
295  pd += start_offset;
296 
297  for (; h; --h) {
298  for (i = 0; i < w; ++i) {
299  rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
300  ++pd;
301  }
302  pd += horiz_offset;
303  }
304  } else {
305  BUG();
306  }
307 }
309 
310 static int rfbi_transfer_area(struct omap_dss_device *dssdev,
311  void (*callback)(void *data), void *data)
312 {
313  u32 l;
314  int r;
315  struct omap_overlay_manager *mgr = dssdev->output->manager;
316  u16 width = rfbi.timings.x_res;
317  u16 height = rfbi.timings.y_res;
318 
319  /*BUG_ON(callback == 0);*/
320  BUG_ON(rfbi.framedone_callback != NULL);
321 
322  DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 
324  dss_mgr_set_timings(mgr, &rfbi.timings);
325 
326  r = dss_mgr_enable(mgr);
327  if (r)
328  return r;
329 
330  rfbi.framedone_callback = callback;
331  rfbi.framedone_callback_data = data;
332 
333  rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
334 
335  l = rfbi_read_reg(RFBI_CONTROL);
336  l = FLD_MOD(l, 1, 0, 0); /* enable */
337  if (!rfbi.te_enabled)
338  l = FLD_MOD(l, 1, 4, 4); /* ITE */
339 
340  rfbi_write_reg(RFBI_CONTROL, l);
341 
342  return 0;
343 }
344 
345 static void framedone_callback(void *data, u32 mask)
346 {
347  void (*callback)(void *data);
348 
349  DSSDBG("FRAMEDONE\n");
350 
351  REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
352 
353  callback = rfbi.framedone_callback;
354  rfbi.framedone_callback = NULL;
355 
356  if (callback != NULL)
357  callback(rfbi.framedone_callback_data);
358 }
359 
360 #if 1 /* VERBOSE */
361 static void rfbi_print_timings(void)
362 {
363  u32 l;
364  u32 time;
365 
366  l = rfbi_read_reg(RFBI_CONFIG(0));
367  time = 1000000000 / rfbi.l4_khz;
368  if (l & (1 << 4))
369  time *= 2;
370 
371  DSSDBG("Tick time %u ps\n", time);
372  l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
373  DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
374  "REONTIME %d, REOFFTIME %d\n",
375  l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
376  (l >> 20) & 0x0f, (l >> 24) & 0x3f);
377 
378  l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
379  DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
380  "ACCESSTIME %d\n",
381  (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
382  (l >> 22) & 0x3f);
383 }
384 #else
385 static void rfbi_print_timings(void) {}
386 #endif
387 
388 
389 
390 
391 static u32 extif_clk_period;
392 
393 static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
394 {
395  int bus_tick = extif_clk_period * div;
396  return (ps + bus_tick - 1) / bus_tick * bus_tick;
397 }
398 
399 static int calc_reg_timing(struct rfbi_timings *t, int div)
400 {
401  t->clk_div = div;
402 
403  t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
404 
405  t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
406  t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
407  t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
408 
409  t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
410  t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
411  t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
412 
413  t->access_time = round_to_extif_ticks(t->access_time, div);
414  t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
415  t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
416 
417  DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
419  DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
421  t->we_cycle_time);
422  DSSDBG("[reg]rdaccess %d cspulse %d\n",
423  t->access_time, t->cs_pulse_width);
424 
425  return rfbi_convert_timings(t);
426 }
427 
428 static int calc_extif_timings(struct rfbi_timings *t)
429 {
430  u32 max_clk_div;
431  int div;
432 
433  rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
434  for (div = 1; div <= max_clk_div; div++) {
435  if (calc_reg_timing(t, div) == 0)
436  break;
437  }
438 
439  if (div <= max_clk_div)
440  return 0;
441 
442  DSSERR("can't setup timings\n");
443  return -1;
444 }
445 
446 
447 static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
448 {
449  int r;
450 
451  if (!t->converted) {
452  r = calc_extif_timings(t);
453  if (r < 0)
454  DSSERR("Failed to calc timings\n");
455  }
456 
457  BUG_ON(!t->converted);
458 
459  rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
460  rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
461 
462  /* TIMEGRANULARITY */
463  REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
464  (t->tim[2] ? 1 : 0), 4, 4);
465 
466  rfbi_print_timings();
467 }
468 
469 static int ps_to_rfbi_ticks(int time, int div)
470 {
471  unsigned long tick_ps;
472  int ret;
473 
474  /* Calculate in picosecs to yield more exact results */
475  tick_ps = 1000000000 / (rfbi.l4_khz) * div;
476 
477  ret = (time + tick_ps - 1) / tick_ps;
478 
479  return ret;
480 }
481 
482 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
483 {
484  *clk_period = 1000000000 / rfbi.l4_khz;
485  *max_clk_div = 2;
486 }
487 
488 static int rfbi_convert_timings(struct rfbi_timings *t)
489 {
490  u32 l;
491  int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
492  int actim, recyc, wecyc;
493  int div = t->clk_div;
494 
495  if (div <= 0 || div > 2)
496  return -1;
497 
498  /* Make sure that after conversion it still holds that:
499  * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
500  * csoff > cson, csoff >= max(weoff, reoff), actim > reon
501  */
502  weon = ps_to_rfbi_ticks(t->we_on_time, div);
503  weoff = ps_to_rfbi_ticks(t->we_off_time, div);
504  if (weoff <= weon)
505  weoff = weon + 1;
506  if (weon > 0x0f)
507  return -1;
508  if (weoff > 0x3f)
509  return -1;
510 
511  reon = ps_to_rfbi_ticks(t->re_on_time, div);
512  reoff = ps_to_rfbi_ticks(t->re_off_time, div);
513  if (reoff <= reon)
514  reoff = reon + 1;
515  if (reon > 0x0f)
516  return -1;
517  if (reoff > 0x3f)
518  return -1;
519 
520  cson = ps_to_rfbi_ticks(t->cs_on_time, div);
521  csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
522  if (csoff <= cson)
523  csoff = cson + 1;
524  if (csoff < max(weoff, reoff))
525  csoff = max(weoff, reoff);
526  if (cson > 0x0f)
527  return -1;
528  if (csoff > 0x3f)
529  return -1;
530 
531  l = cson;
532  l |= csoff << 4;
533  l |= weon << 10;
534  l |= weoff << 14;
535  l |= reon << 20;
536  l |= reoff << 24;
537 
538  t->tim[0] = l;
539 
540  actim = ps_to_rfbi_ticks(t->access_time, div);
541  if (actim <= reon)
542  actim = reon + 1;
543  if (actim > 0x3f)
544  return -1;
545 
546  wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
547  if (wecyc < weoff)
548  wecyc = weoff;
549  if (wecyc > 0x3f)
550  return -1;
551 
552  recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
553  if (recyc < reoff)
554  recyc = reoff;
555  if (recyc > 0x3f)
556  return -1;
557 
558  cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
559  if (cs_pulse > 0x3f)
560  return -1;
561 
562  l = wecyc;
563  l |= recyc << 6;
564  l |= cs_pulse << 12;
565  l |= actim << 22;
566 
567  t->tim[1] = l;
568 
569  t->tim[2] = div - 1;
570 
571  t->converted = 1;
572 
573  return 0;
574 }
575 
576 /* xxx FIX module selection missing */
578  unsigned hs_pulse_time, unsigned vs_pulse_time,
579  int hs_pol_inv, int vs_pol_inv, int extif_div)
580 {
581  int hs, vs;
582  int min;
583  u32 l;
584 
585  hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
586  vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
587  if (hs < 2)
588  return -EDOM;
589  if (mode == OMAP_DSS_RFBI_TE_MODE_2)
590  min = 2;
591  else /* OMAP_DSS_RFBI_TE_MODE_1 */
592  min = 4;
593  if (vs < min)
594  return -EDOM;
595  if (vs == hs)
596  return -EINVAL;
597  rfbi.te_mode = mode;
598  DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
599  mode, hs, vs, hs_pol_inv, vs_pol_inv);
600 
601  rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
602  rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
603 
604  l = rfbi_read_reg(RFBI_CONFIG(0));
605  if (hs_pol_inv)
606  l &= ~(1 << 21);
607  else
608  l |= 1 << 21;
609  if (vs_pol_inv)
610  l &= ~(1 << 20);
611  else
612  l |= 1 << 20;
613 
614  return 0;
615 }
617 
618 /* xxx FIX module selection missing */
619 int omap_rfbi_enable_te(bool enable, unsigned line)
620 {
621  u32 l;
622 
623  DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
624  if (line > (1 << 11) - 1)
625  return -EINVAL;
626 
627  l = rfbi_read_reg(RFBI_CONFIG(0));
628  l &= ~(0x3 << 2);
629  if (enable) {
630  rfbi.te_enabled = 1;
631  l |= rfbi.te_mode << 2;
632  } else
633  rfbi.te_enabled = 0;
634  rfbi_write_reg(RFBI_CONFIG(0), l);
635  rfbi_write_reg(RFBI_LINE_NUMBER, line);
636 
637  return 0;
638 }
640 
641 static int rfbi_configure(int rfbi_module, int bpp, int lines)
642 {
643  u32 l;
644  int cycle1 = 0, cycle2 = 0, cycle3 = 0;
645  enum omap_rfbi_cycleformat cycleformat;
648 
649  switch (bpp) {
650  case 12:
651  datatype = OMAP_DSS_RFBI_DATATYPE_12;
652  break;
653  case 16:
654  datatype = OMAP_DSS_RFBI_DATATYPE_16;
655  break;
656  case 18:
657  datatype = OMAP_DSS_RFBI_DATATYPE_18;
658  break;
659  case 24:
660  datatype = OMAP_DSS_RFBI_DATATYPE_24;
661  break;
662  default:
663  BUG();
664  return 1;
665  }
666  rfbi.datatype = datatype;
667 
668  switch (lines) {
669  case 8:
670  parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
671  break;
672  case 9:
673  parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
674  break;
675  case 12:
676  parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
677  break;
678  case 16:
679  parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
680  break;
681  default:
682  BUG();
683  return 1;
684  }
685  rfbi.parallelmode = parallelmode;
686 
687  if ((bpp % lines) == 0) {
688  switch (bpp / lines) {
689  case 1:
690  cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
691  break;
692  case 2:
693  cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
694  break;
695  case 3:
696  cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
697  break;
698  default:
699  BUG();
700  return 1;
701  }
702  } else if ((2 * bpp % lines) == 0) {
703  if ((2 * bpp / lines) == 3)
704  cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
705  else {
706  BUG();
707  return 1;
708  }
709  } else {
710  BUG();
711  return 1;
712  }
713 
714  switch (cycleformat) {
716  cycle1 = lines;
717  break;
718 
720  cycle1 = lines;
721  cycle2 = lines;
722  break;
723 
725  cycle1 = lines;
726  cycle2 = lines;
727  cycle3 = lines;
728  break;
729 
731  cycle1 = lines;
732  cycle2 = (lines / 2) | ((lines / 2) << 16);
733  cycle3 = (lines << 16);
734  break;
735  }
736 
737  REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
738 
739  l = 0;
740  l |= FLD_VAL(parallelmode, 1, 0);
741  l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
742  l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
743  l |= FLD_VAL(datatype, 6, 5);
744  /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
745  l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
746  l |= FLD_VAL(cycleformat, 10, 9);
747  l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
748  l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
749  l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
750  l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
751  l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
752  l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
753  l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
754  rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
755 
756  rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
757  rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
758  rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
759 
760 
761  l = rfbi_read_reg(RFBI_CONTROL);
762  l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
763  l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
764  rfbi_write_reg(RFBI_CONTROL, l);
765 
766 
767  DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
768  bpp, lines, cycle1, cycle2, cycle3);
769 
770  return 0;
771 }
772 
774 {
775  return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
776  rfbi.data_lines);
777 }
779 
780 int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
781  void *data)
782 {
783  return rfbi_transfer_area(dssdev, callback, data);
784 }
786 
788 {
789  rfbi.timings.x_res = w;
790  rfbi.timings.y_res = h;
791 }
793 
795 {
796  rfbi.pixel_size = pixel_size;
797 }
799 
801 {
802  rfbi.data_lines = data_lines;
803 }
805 
807  struct rfbi_timings *timings)
808 {
809  rfbi.intf_timings = *timings;
810 }
812 
813 static void rfbi_dump_regs(struct seq_file *s)
814 {
815 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
816 
817  if (rfbi_runtime_get())
818  return;
819 
826  DUMPREG(RFBI_CMD);
831 
832  DUMPREG(RFBI_CONFIG(0));
838 
839  DUMPREG(RFBI_CONFIG(1));
845 
848 
849  rfbi_runtime_put();
850 #undef DUMPREG
851 }
852 
853 static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
854 {
855  struct omap_overlay_manager *mgr = dssdev->output->manager;
857 
858  mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
859 
860  mgr_config.stallmode = true;
861  /* Do we need fifohandcheck for RFBI? */
862  mgr_config.fifohandcheck = false;
863 
864  mgr_config.video_port_width = rfbi.pixel_size;
865  mgr_config.lcden_sig_polarity = 0;
866 
868 
869  /*
870  * Set rfbi.timings with default values, the x_res and y_res fields
871  * are expected to be already configured by the panel driver via
872  * omapdss_rfbi_set_size()
873  */
874  rfbi.timings.hsw = 1;
875  rfbi.timings.hfp = 1;
876  rfbi.timings.hbp = 1;
877  rfbi.timings.vsw = 1;
878  rfbi.timings.vfp = 0;
879  rfbi.timings.vbp = 0;
880 
881  rfbi.timings.interlace = false;
882  rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883  rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884  rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885  rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886  rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887 
888  dss_mgr_set_timings(mgr, &rfbi.timings);
889 }
890 
892 {
893  struct omap_dss_output *out = dssdev->output;
894  int r;
895 
896  if (out == NULL || out->manager == NULL) {
897  DSSERR("failed to enable display: no output/manager\n");
898  return -ENODEV;
899  }
900 
901  r = rfbi_runtime_get();
902  if (r)
903  return r;
904 
905  r = omap_dss_start_device(dssdev);
906  if (r) {
907  DSSERR("failed to start device\n");
908  goto err0;
909  }
910 
913  if (r) {
914  DSSERR("can't get FRAMEDONE irq\n");
915  goto err1;
916  }
917 
918  rfbi_config_lcd_manager(dssdev);
919 
920  rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
921  rfbi.data_lines);
922 
923  rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
924 
925  return 0;
926 err1:
927  omap_dss_stop_device(dssdev);
928 err0:
929  rfbi_runtime_put();
930  return r;
931 }
933 
935 {
938  omap_dss_stop_device(dssdev);
939 
940  rfbi_runtime_put();
941 }
943 
944 static int __init rfbi_init_display(struct omap_dss_device *dssdev)
945 {
946  rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
947  return 0;
948 }
949 
950 static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
951 {
952  struct omap_dss_board_info *pdata = pdev->dev.platform_data;
953  const char *def_disp_name = dss_get_default_display_name();
954  struct omap_dss_device *def_dssdev;
955  int i;
956 
957  def_dssdev = NULL;
958 
959  for (i = 0; i < pdata->num_devices; ++i) {
960  struct omap_dss_device *dssdev = pdata->devices[i];
961 
962  if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
963  continue;
964 
965  if (def_dssdev == NULL)
966  def_dssdev = dssdev;
967 
968  if (def_disp_name != NULL &&
969  strcmp(dssdev->name, def_disp_name) == 0) {
970  def_dssdev = dssdev;
971  break;
972  }
973  }
974 
975  return def_dssdev;
976 }
977 
978 static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
979 {
980  struct omap_dss_device *plat_dssdev;
981  struct omap_dss_device *dssdev;
982  int r;
983 
984  plat_dssdev = rfbi_find_dssdev(rfbidev);
985 
986  if (!plat_dssdev)
987  return;
988 
989  dssdev = dss_alloc_and_init_device(&rfbidev->dev);
990  if (!dssdev)
991  return;
992 
993  dss_copy_device_pdata(dssdev, plat_dssdev);
994 
995  r = rfbi_init_display(dssdev);
996  if (r) {
997  DSSERR("device %s init failed: %d\n", dssdev->name, r);
998  dss_put_device(dssdev);
999  return;
1000  }
1001 
1002  r = dss_add_device(dssdev);
1003  if (r) {
1004  DSSERR("device %s register failed: %d\n", dssdev->name, r);
1005  dss_put_device(dssdev);
1006  return;
1007  }
1008 }
1009 
1010 static void __init rfbi_init_output(struct platform_device *pdev)
1011 {
1012  struct omap_dss_output *out = &rfbi.output;
1013 
1014  out->pdev = pdev;
1015  out->id = OMAP_DSS_OUTPUT_DBI;
1016  out->type = OMAP_DISPLAY_TYPE_DBI;
1017 
1018  dss_register_output(out);
1019 }
1020 
1021 static void __exit rfbi_uninit_output(struct platform_device *pdev)
1022 {
1023  struct omap_dss_output *out = &rfbi.output;
1024 
1025  dss_unregister_output(out);
1026 }
1027 
1028 /* RFBI HW IP initialisation */
1029 static int __init omap_rfbihw_probe(struct platform_device *pdev)
1030 {
1031  u32 rev;
1032  struct resource *rfbi_mem;
1033  struct clk *clk;
1034  int r;
1035 
1036  rfbi.pdev = pdev;
1037 
1038  sema_init(&rfbi.bus_lock, 1);
1039 
1040  rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
1041  if (!rfbi_mem) {
1042  DSSERR("can't get IORESOURCE_MEM RFBI\n");
1043  return -EINVAL;
1044  }
1045 
1046  rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
1047  resource_size(rfbi_mem));
1048  if (!rfbi.base) {
1049  DSSERR("can't ioremap RFBI\n");
1050  return -ENOMEM;
1051  }
1052 
1053  clk = clk_get(&pdev->dev, "ick");
1054  if (IS_ERR(clk)) {
1055  DSSERR("can't get ick\n");
1056  return PTR_ERR(clk);
1057  }
1058 
1059  rfbi.l4_khz = clk_get_rate(clk) / 1000;
1060 
1061  clk_put(clk);
1062 
1063  pm_runtime_enable(&pdev->dev);
1064 
1065  r = rfbi_runtime_get();
1066  if (r)
1067  goto err_runtime_get;
1068 
1069  msleep(10);
1070 
1071  rev = rfbi_read_reg(RFBI_REVISION);
1072  dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
1073  FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1074 
1075  rfbi_runtime_put();
1076 
1077  dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1078 
1079  rfbi_init_output(pdev);
1080 
1081  rfbi_probe_pdata(pdev);
1082 
1083  return 0;
1084 
1085 err_runtime_get:
1086  pm_runtime_disable(&pdev->dev);
1087  return r;
1088 }
1089 
1090 static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1091 {
1093 
1094  rfbi_uninit_output(pdev);
1095 
1096  pm_runtime_disable(&pdev->dev);
1097 
1098  return 0;
1099 }
1100 
1101 static int rfbi_runtime_suspend(struct device *dev)
1102 {
1104 
1105  return 0;
1106 }
1107 
1108 static int rfbi_runtime_resume(struct device *dev)
1109 {
1110  int r;
1111 
1112  r = dispc_runtime_get();
1113  if (r < 0)
1114  return r;
1115 
1116  return 0;
1117 }
1118 
1119 static const struct dev_pm_ops rfbi_pm_ops = {
1120  .runtime_suspend = rfbi_runtime_suspend,
1121  .runtime_resume = rfbi_runtime_resume,
1122 };
1123 
1124 static struct platform_driver omap_rfbihw_driver = {
1125  .remove = __exit_p(omap_rfbihw_remove),
1126  .driver = {
1127  .name = "omapdss_rfbi",
1128  .owner = THIS_MODULE,
1129  .pm = &rfbi_pm_ops,
1130  },
1131 };
1132 
1134 {
1135  return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe);
1136 }
1137 
1139 {
1140  platform_driver_unregister(&omap_rfbihw_driver);
1141 }