PageRenderTime 32ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/video/omap2/omapfb/omapfb-main.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 2506 lines | 1950 code | 446 blank | 110 comment | 448 complexity | 5661e5f3721ede936da396b5fb79743e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * linux/drivers/video/omap2/omapfb-main.c
  3. *
  4. * Copyright (C) 2008 Nokia Corporation
  5. * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
  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. #include <linux/module.h>
  23. #include <linux/delay.h>
  24. #include <linux/slab.h>
  25. #include <linux/fb.h>
  26. #include <linux/dma-mapping.h>
  27. #include <linux/vmalloc.h>
  28. #include <linux/device.h>
  29. #include <linux/platform_device.h>
  30. #include <linux/omapfb.h>
  31. #include <linux/wait.h>
  32. #include <video/omapdss.h>
  33. #include <plat/vram.h>
  34. #include <plat/vrfb.h>
  35. #include "omapfb.h"
  36. #define MODULE_NAME "omapfb"
  37. #define OMAPFB_PLANE_XRES_MIN 8
  38. #define OMAPFB_PLANE_YRES_MIN 8
  39. static char *def_mode;
  40. static char *def_vram;
  41. static int def_vrfb;
  42. static int def_rotate;
  43. static int def_mirror;
  44. #ifdef DEBUG
  45. unsigned int omapfb_debug;
  46. module_param_named(debug, omapfb_debug, bool, 0644);
  47. static unsigned int omapfb_test_pattern;
  48. module_param_named(test, omapfb_test_pattern, bool, 0644);
  49. #endif
  50. static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
  51. static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
  52. struct omap_dss_device *dssdev);
  53. #ifdef DEBUG
  54. static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
  55. {
  56. struct fb_var_screeninfo *var = &fbi->var;
  57. struct fb_fix_screeninfo *fix = &fbi->fix;
  58. void __iomem *addr = fbi->screen_base;
  59. const unsigned bytespp = var->bits_per_pixel >> 3;
  60. const unsigned line_len = fix->line_length / bytespp;
  61. int r = (color >> 16) & 0xff;
  62. int g = (color >> 8) & 0xff;
  63. int b = (color >> 0) & 0xff;
  64. if (var->bits_per_pixel == 16) {
  65. u16 __iomem *p = (u16 __iomem *)addr;
  66. p += y * line_len + x;
  67. r = r * 32 / 256;
  68. g = g * 64 / 256;
  69. b = b * 32 / 256;
  70. __raw_writew((r << 11) | (g << 5) | (b << 0), p);
  71. } else if (var->bits_per_pixel == 24) {
  72. u8 __iomem *p = (u8 __iomem *)addr;
  73. p += (y * line_len + x) * 3;
  74. __raw_writeb(b, p + 0);
  75. __raw_writeb(g, p + 1);
  76. __raw_writeb(r, p + 2);
  77. } else if (var->bits_per_pixel == 32) {
  78. u32 __iomem *p = (u32 __iomem *)addr;
  79. p += y * line_len + x;
  80. __raw_writel(color, p);
  81. }
  82. }
  83. static void fill_fb(struct fb_info *fbi)
  84. {
  85. struct fb_var_screeninfo *var = &fbi->var;
  86. const short w = var->xres_virtual;
  87. const short h = var->yres_virtual;
  88. void __iomem *addr = fbi->screen_base;
  89. int y, x;
  90. if (!addr)
  91. return;
  92. DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
  93. for (y = 0; y < h; y++) {
  94. for (x = 0; x < w; x++) {
  95. if (x < 20 && y < 20)
  96. draw_pixel(fbi, x, y, 0xffffff);
  97. else if (x < 20 && (y > 20 && y < h - 20))
  98. draw_pixel(fbi, x, y, 0xff);
  99. else if (y < 20 && (x > 20 && x < w - 20))
  100. draw_pixel(fbi, x, y, 0xff00);
  101. else if (x > w - 20 && (y > 20 && y < h - 20))
  102. draw_pixel(fbi, x, y, 0xff0000);
  103. else if (y > h - 20 && (x > 20 && x < w - 20))
  104. draw_pixel(fbi, x, y, 0xffff00);
  105. else if (x == 20 || x == w - 20 ||
  106. y == 20 || y == h - 20)
  107. draw_pixel(fbi, x, y, 0xffffff);
  108. else if (x == y || w - x == h - y)
  109. draw_pixel(fbi, x, y, 0xff00ff);
  110. else if (w - x == y || x == h - y)
  111. draw_pixel(fbi, x, y, 0x00ffff);
  112. else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
  113. int t = x * 3 / w;
  114. unsigned r = 0, g = 0, b = 0;
  115. unsigned c;
  116. if (var->bits_per_pixel == 16) {
  117. if (t == 0)
  118. b = (y % 32) * 256 / 32;
  119. else if (t == 1)
  120. g = (y % 64) * 256 / 64;
  121. else if (t == 2)
  122. r = (y % 32) * 256 / 32;
  123. } else {
  124. if (t == 0)
  125. b = (y % 256);
  126. else if (t == 1)
  127. g = (y % 256);
  128. else if (t == 2)
  129. r = (y % 256);
  130. }
  131. c = (r << 16) | (g << 8) | (b << 0);
  132. draw_pixel(fbi, x, y, c);
  133. } else {
  134. draw_pixel(fbi, x, y, 0);
  135. }
  136. }
  137. }
  138. }
  139. #endif
  140. static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
  141. {
  142. const struct vrfb *vrfb = &ofbi->region->vrfb;
  143. unsigned offset;
  144. switch (rot) {
  145. case FB_ROTATE_UR:
  146. offset = 0;
  147. break;
  148. case FB_ROTATE_CW:
  149. offset = vrfb->yoffset;
  150. break;
  151. case FB_ROTATE_UD:
  152. offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
  153. break;
  154. case FB_ROTATE_CCW:
  155. offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
  156. break;
  157. default:
  158. BUG();
  159. }
  160. offset *= vrfb->bytespp;
  161. return offset;
  162. }
  163. static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
  164. {
  165. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  166. return ofbi->region->vrfb.paddr[rot]
  167. + omapfb_get_vrfb_offset(ofbi, rot);
  168. } else {
  169. return ofbi->region->paddr;
  170. }
  171. }
  172. static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
  173. {
  174. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
  175. return ofbi->region->vrfb.paddr[0];
  176. else
  177. return ofbi->region->paddr;
  178. }
  179. static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
  180. {
  181. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
  182. return ofbi->region->vrfb.vaddr[0];
  183. else
  184. return ofbi->region->vaddr;
  185. }
  186. static struct omapfb_colormode omapfb_colormodes[] = {
  187. {
  188. .dssmode = OMAP_DSS_COLOR_UYVY,
  189. .bits_per_pixel = 16,
  190. .nonstd = OMAPFB_COLOR_YUV422,
  191. }, {
  192. .dssmode = OMAP_DSS_COLOR_YUV2,
  193. .bits_per_pixel = 16,
  194. .nonstd = OMAPFB_COLOR_YUY422,
  195. }, {
  196. .dssmode = OMAP_DSS_COLOR_ARGB16,
  197. .bits_per_pixel = 16,
  198. .red = { .length = 4, .offset = 8, .msb_right = 0 },
  199. .green = { .length = 4, .offset = 4, .msb_right = 0 },
  200. .blue = { .length = 4, .offset = 0, .msb_right = 0 },
  201. .transp = { .length = 4, .offset = 12, .msb_right = 0 },
  202. }, {
  203. .dssmode = OMAP_DSS_COLOR_RGB16,
  204. .bits_per_pixel = 16,
  205. .red = { .length = 5, .offset = 11, .msb_right = 0 },
  206. .green = { .length = 6, .offset = 5, .msb_right = 0 },
  207. .blue = { .length = 5, .offset = 0, .msb_right = 0 },
  208. .transp = { .length = 0, .offset = 0, .msb_right = 0 },
  209. }, {
  210. .dssmode = OMAP_DSS_COLOR_RGB24P,
  211. .bits_per_pixel = 24,
  212. .red = { .length = 8, .offset = 16, .msb_right = 0 },
  213. .green = { .length = 8, .offset = 8, .msb_right = 0 },
  214. .blue = { .length = 8, .offset = 0, .msb_right = 0 },
  215. .transp = { .length = 0, .offset = 0, .msb_right = 0 },
  216. }, {
  217. .dssmode = OMAP_DSS_COLOR_RGB24U,
  218. .bits_per_pixel = 32,
  219. .red = { .length = 8, .offset = 16, .msb_right = 0 },
  220. .green = { .length = 8, .offset = 8, .msb_right = 0 },
  221. .blue = { .length = 8, .offset = 0, .msb_right = 0 },
  222. .transp = { .length = 0, .offset = 0, .msb_right = 0 },
  223. }, {
  224. .dssmode = OMAP_DSS_COLOR_ARGB32,
  225. .bits_per_pixel = 32,
  226. .red = { .length = 8, .offset = 16, .msb_right = 0 },
  227. .green = { .length = 8, .offset = 8, .msb_right = 0 },
  228. .blue = { .length = 8, .offset = 0, .msb_right = 0 },
  229. .transp = { .length = 8, .offset = 24, .msb_right = 0 },
  230. }, {
  231. .dssmode = OMAP_DSS_COLOR_RGBA32,
  232. .bits_per_pixel = 32,
  233. .red = { .length = 8, .offset = 24, .msb_right = 0 },
  234. .green = { .length = 8, .offset = 16, .msb_right = 0 },
  235. .blue = { .length = 8, .offset = 8, .msb_right = 0 },
  236. .transp = { .length = 8, .offset = 0, .msb_right = 0 },
  237. }, {
  238. .dssmode = OMAP_DSS_COLOR_RGBX32,
  239. .bits_per_pixel = 32,
  240. .red = { .length = 8, .offset = 24, .msb_right = 0 },
  241. .green = { .length = 8, .offset = 16, .msb_right = 0 },
  242. .blue = { .length = 8, .offset = 8, .msb_right = 0 },
  243. .transp = { .length = 0, .offset = 0, .msb_right = 0 },
  244. },
  245. };
  246. static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
  247. struct omapfb_colormode *color)
  248. {
  249. bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
  250. {
  251. return f1->length == f2->length &&
  252. f1->offset == f2->offset &&
  253. f1->msb_right == f2->msb_right;
  254. }
  255. if (var->bits_per_pixel == 0 ||
  256. var->red.length == 0 ||
  257. var->blue.length == 0 ||
  258. var->green.length == 0)
  259. return 0;
  260. return var->bits_per_pixel == color->bits_per_pixel &&
  261. cmp_component(&var->red, &color->red) &&
  262. cmp_component(&var->green, &color->green) &&
  263. cmp_component(&var->blue, &color->blue) &&
  264. cmp_component(&var->transp, &color->transp);
  265. }
  266. static void assign_colormode_to_var(struct fb_var_screeninfo *var,
  267. struct omapfb_colormode *color)
  268. {
  269. var->bits_per_pixel = color->bits_per_pixel;
  270. var->nonstd = color->nonstd;
  271. var->red = color->red;
  272. var->green = color->green;
  273. var->blue = color->blue;
  274. var->transp = color->transp;
  275. }
  276. int omapfb_mode_to_dss_mode(struct fb_var_screeninfo *var,
  277. enum omap_color_mode *mode)
  278. {
  279. enum omap_color_mode dssmode;
  280. int i;
  281. /* first match with nonstd field */
  282. if (var->nonstd) {
  283. for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
  284. struct omapfb_colormode *m = &omapfb_colormodes[i];
  285. if (var->nonstd == m->nonstd) {
  286. assign_colormode_to_var(var, m);
  287. *mode = m->dssmode;
  288. return 0;
  289. }
  290. }
  291. return -EINVAL;
  292. }
  293. /* then try exact match of bpp and colors */
  294. for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
  295. struct omapfb_colormode *m = &omapfb_colormodes[i];
  296. if (cmp_var_to_colormode(var, m)) {
  297. assign_colormode_to_var(var, m);
  298. *mode = m->dssmode;
  299. return 0;
  300. }
  301. }
  302. /* match with bpp if user has not filled color fields
  303. * properly */
  304. switch (var->bits_per_pixel) {
  305. case 1:
  306. dssmode = OMAP_DSS_COLOR_CLUT1;
  307. break;
  308. case 2:
  309. dssmode = OMAP_DSS_COLOR_CLUT2;
  310. break;
  311. case 4:
  312. dssmode = OMAP_DSS_COLOR_CLUT4;
  313. break;
  314. case 8:
  315. dssmode = OMAP_DSS_COLOR_CLUT8;
  316. break;
  317. case 12:
  318. dssmode = OMAP_DSS_COLOR_RGB12U;
  319. break;
  320. case 16:
  321. dssmode = OMAP_DSS_COLOR_RGB16;
  322. break;
  323. case 24:
  324. dssmode = OMAP_DSS_COLOR_RGB24P;
  325. break;
  326. case 32:
  327. dssmode = OMAP_DSS_COLOR_ARGB32;
  328. break;
  329. default:
  330. return -EINVAL;
  331. }
  332. for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
  333. struct omapfb_colormode *m = &omapfb_colormodes[i];
  334. if (dssmode == m->dssmode) {
  335. assign_colormode_to_var(var, m);
  336. *mode = m->dssmode;
  337. return 0;
  338. }
  339. }
  340. return -EINVAL;
  341. }
  342. EXPORT_SYMBOL(omapfb_mode_to_dss_mode);
  343. static int check_fb_res_bounds(struct fb_var_screeninfo *var)
  344. {
  345. int xres_min = OMAPFB_PLANE_XRES_MIN;
  346. int xres_max = 2048;
  347. int yres_min = OMAPFB_PLANE_YRES_MIN;
  348. int yres_max = 2048;
  349. /* XXX: some applications seem to set virtual res to 0. */
  350. if (var->xres_virtual == 0)
  351. var->xres_virtual = var->xres;
  352. if (var->yres_virtual == 0)
  353. var->yres_virtual = var->yres;
  354. if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
  355. return -EINVAL;
  356. if (var->xres < xres_min)
  357. var->xres = xres_min;
  358. if (var->yres < yres_min)
  359. var->yres = yres_min;
  360. if (var->xres > xres_max)
  361. var->xres = xres_max;
  362. if (var->yres > yres_max)
  363. var->yres = yres_max;
  364. if (var->xres > var->xres_virtual)
  365. var->xres = var->xres_virtual;
  366. if (var->yres > var->yres_virtual)
  367. var->yres = var->yres_virtual;
  368. return 0;
  369. }
  370. static void shrink_height(unsigned long max_frame_size,
  371. struct fb_var_screeninfo *var)
  372. {
  373. DBG("can't fit FB into memory, reducing y\n");
  374. var->yres_virtual = max_frame_size /
  375. (var->xres_virtual * var->bits_per_pixel >> 3);
  376. if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
  377. var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
  378. if (var->yres > var->yres_virtual)
  379. var->yres = var->yres_virtual;
  380. }
  381. static void shrink_width(unsigned long max_frame_size,
  382. struct fb_var_screeninfo *var)
  383. {
  384. DBG("can't fit FB into memory, reducing x\n");
  385. var->xres_virtual = max_frame_size / var->yres_virtual /
  386. (var->bits_per_pixel >> 3);
  387. if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
  388. var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
  389. if (var->xres > var->xres_virtual)
  390. var->xres = var->xres_virtual;
  391. }
  392. static int check_vrfb_fb_size(unsigned long region_size,
  393. const struct fb_var_screeninfo *var)
  394. {
  395. unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
  396. var->yres_virtual, var->bits_per_pixel >> 3);
  397. return min_phys_size > region_size ? -EINVAL : 0;
  398. }
  399. static int check_fb_size(const struct omapfb_info *ofbi,
  400. struct fb_var_screeninfo *var)
  401. {
  402. unsigned long max_frame_size = ofbi->region->size;
  403. int bytespp = var->bits_per_pixel >> 3;
  404. unsigned long line_size = var->xres_virtual * bytespp;
  405. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  406. /* One needs to check for both VRFB and OMAPFB limitations. */
  407. if (check_vrfb_fb_size(max_frame_size, var))
  408. shrink_height(omap_vrfb_max_height(
  409. max_frame_size, var->xres_virtual, bytespp) *
  410. line_size, var);
  411. if (check_vrfb_fb_size(max_frame_size, var)) {
  412. DBG("cannot fit FB to memory\n");
  413. return -EINVAL;
  414. }
  415. return 0;
  416. }
  417. DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
  418. if (line_size * var->yres_virtual > max_frame_size)
  419. shrink_height(max_frame_size, var);
  420. if (line_size * var->yres_virtual > max_frame_size) {
  421. shrink_width(max_frame_size, var);
  422. line_size = var->xres_virtual * bytespp;
  423. }
  424. if (line_size * var->yres_virtual > max_frame_size) {
  425. DBG("cannot fit FB to memory\n");
  426. return -EINVAL;
  427. }
  428. return 0;
  429. }
  430. /*
  431. * Consider if VRFB assisted rotation is in use and if the virtual space for
  432. * the zero degree view needs to be mapped. The need for mapping also acts as
  433. * the trigger for setting up the hardware on the context in question. This
  434. * ensures that one does not attempt to access the virtual view before the
  435. * hardware is serving the address translations.
  436. */
  437. static int setup_vrfb_rotation(struct fb_info *fbi)
  438. {
  439. struct omapfb_info *ofbi = FB2OFB(fbi);
  440. struct omapfb2_mem_region *rg = ofbi->region;
  441. struct vrfb *vrfb = &rg->vrfb;
  442. struct fb_var_screeninfo *var = &fbi->var;
  443. struct fb_fix_screeninfo *fix = &fbi->fix;
  444. unsigned bytespp;
  445. bool yuv_mode;
  446. enum omap_color_mode mode;
  447. int r;
  448. bool reconf;
  449. if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
  450. return 0;
  451. DBG("setup_vrfb_rotation\n");
  452. r = omapfb_mode_to_dss_mode(var, &mode);
  453. if (r)
  454. return r;
  455. bytespp = var->bits_per_pixel >> 3;
  456. yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
  457. /* We need to reconfigure VRFB if the resolution changes, if yuv mode
  458. * is enabled/disabled, or if bytes per pixel changes */
  459. /* XXX we shouldn't allow this when framebuffer is mmapped */
  460. reconf = false;
  461. if (yuv_mode != vrfb->yuv_mode)
  462. reconf = true;
  463. else if (bytespp != vrfb->bytespp)
  464. reconf = true;
  465. else if (vrfb->xres != var->xres_virtual ||
  466. vrfb->yres != var->yres_virtual)
  467. reconf = true;
  468. if (vrfb->vaddr[0] && reconf) {
  469. fbi->screen_base = NULL;
  470. fix->smem_start = 0;
  471. fix->smem_len = 0;
  472. iounmap(vrfb->vaddr[0]);
  473. vrfb->vaddr[0] = NULL;
  474. DBG("setup_vrfb_rotation: reset fb\n");
  475. }
  476. if (vrfb->vaddr[0])
  477. return 0;
  478. omap_vrfb_setup(&rg->vrfb, rg->paddr,
  479. var->xres_virtual,
  480. var->yres_virtual,
  481. bytespp, yuv_mode);
  482. /* Now one can ioremap the 0 angle view */
  483. r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
  484. if (r)
  485. return r;
  486. /* used by open/write in fbmem.c */
  487. fbi->screen_base = ofbi->region->vrfb.vaddr[0];
  488. fix->smem_start = ofbi->region->vrfb.paddr[0];
  489. switch (var->nonstd) {
  490. case OMAPFB_COLOR_YUV422:
  491. case OMAPFB_COLOR_YUY422:
  492. fix->line_length =
  493. (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
  494. break;
  495. default:
  496. fix->line_length =
  497. (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
  498. break;
  499. }
  500. fix->smem_len = var->yres_virtual * fix->line_length;
  501. return 0;
  502. }
  503. int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
  504. struct fb_var_screeninfo *var)
  505. {
  506. int i;
  507. for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
  508. struct omapfb_colormode *mode = &omapfb_colormodes[i];
  509. if (dssmode == mode->dssmode) {
  510. assign_colormode_to_var(var, mode);
  511. return 0;
  512. }
  513. }
  514. return -ENOENT;
  515. }
  516. void set_fb_fix(struct fb_info *fbi)
  517. {
  518. struct fb_fix_screeninfo *fix = &fbi->fix;
  519. struct fb_var_screeninfo *var = &fbi->var;
  520. struct omapfb_info *ofbi = FB2OFB(fbi);
  521. struct omapfb2_mem_region *rg = ofbi->region;
  522. DBG("set_fb_fix\n");
  523. /* used by open/write in fbmem.c */
  524. fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
  525. /* used by mmap in fbmem.c */
  526. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  527. switch (var->nonstd) {
  528. case OMAPFB_COLOR_YUV422:
  529. case OMAPFB_COLOR_YUY422:
  530. fix->line_length =
  531. (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
  532. break;
  533. default:
  534. fix->line_length =
  535. (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
  536. break;
  537. }
  538. fix->smem_len = var->yres_virtual * fix->line_length;
  539. } else {
  540. /* SGX requires stride to be a multiple of 32 pixels */
  541. int xres_align = ALIGN(var->xres_virtual, 32);
  542. fix->line_length = (xres_align * var->bits_per_pixel) >> 3;
  543. fix->smem_len = rg->size;
  544. }
  545. fix->smem_start = omapfb_get_region_paddr(ofbi);
  546. fix->type = FB_TYPE_PACKED_PIXELS;
  547. if (var->nonstd)
  548. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  549. else {
  550. switch (var->bits_per_pixel) {
  551. case 32:
  552. case 24:
  553. case 16:
  554. case 12:
  555. fix->visual = FB_VISUAL_TRUECOLOR;
  556. /* 12bpp is stored in 16 bits */
  557. break;
  558. case 1:
  559. case 2:
  560. case 4:
  561. case 8:
  562. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  563. break;
  564. }
  565. }
  566. fix->accel = FB_ACCEL_NONE;
  567. fix->xpanstep = 1;
  568. fix->ypanstep = 1;
  569. }
  570. /* check new var and possibly modify it to be ok */
  571. int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
  572. {
  573. struct omapfb_info *ofbi = FB2OFB(fbi);
  574. struct omap_dss_device *display = fb2display(fbi);
  575. enum omap_color_mode mode = 0;
  576. int i;
  577. int r;
  578. u32 w = 0, h = 0;
  579. DBG("check_fb_var %d\n", ofbi->id);
  580. WARN_ON(!atomic_read(&ofbi->region->lock_count));
  581. r = omapfb_mode_to_dss_mode(var, &mode);
  582. if (r) {
  583. DBG("cannot convert var to omap dss mode\n");
  584. return r;
  585. }
  586. for (i = 0; i < ofbi->num_overlays; ++i) {
  587. if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
  588. DBG("invalid mode\n");
  589. return -EINVAL;
  590. }
  591. }
  592. if (var->rotate > 3)
  593. return -EINVAL;
  594. if (check_fb_res_bounds(var))
  595. return -EINVAL;
  596. /* When no memory is allocated ignore the size check */
  597. if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
  598. return -EINVAL;
  599. if (var->xres + var->xoffset > var->xres_virtual)
  600. var->xoffset = var->xres_virtual - var->xres;
  601. if (var->yres + var->yoffset > var->yres_virtual)
  602. var->yoffset = var->yres_virtual - var->yres;
  603. DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
  604. var->xres, var->yres,
  605. var->xres_virtual, var->yres_virtual);
  606. if (display)
  607. omapdss_display_get_dimensions(display, &w, &h);
  608. if (w && h) {
  609. var->width = DIV_ROUND_CLOSEST(w, 1000);
  610. var->height = DIV_ROUND_CLOSEST(h, 1000);
  611. } else {
  612. var->height = -1;
  613. var->width = -1;
  614. }
  615. var->grayscale = 0;
  616. if (display && display->driver->get_timings) {
  617. struct omap_video_timings timings;
  618. display->driver->get_timings(display, &timings);
  619. /* pixclock in ps, the rest in pixclock */
  620. var->pixclock = timings.pixel_clock != 0 ?
  621. KHZ2PICOS(timings.pixel_clock) :
  622. 0;
  623. var->left_margin = timings.hbp;
  624. var->right_margin = timings.hfp;
  625. var->upper_margin = timings.vbp;
  626. var->lower_margin = timings.vfp;
  627. var->hsync_len = timings.hsw;
  628. var->vsync_len = timings.vsw;
  629. } else {
  630. var->pixclock = 0;
  631. var->left_margin = 0;
  632. var->right_margin = 0;
  633. var->upper_margin = 0;
  634. var->lower_margin = 0;
  635. var->hsync_len = 0;
  636. var->vsync_len = 0;
  637. }
  638. /* TODO: get these from panel->config */
  639. var->vmode = FB_VMODE_NONINTERLACED;
  640. var->sync = 0;
  641. return 0;
  642. }
  643. /*
  644. * ---------------------------------------------------------------------------
  645. * fbdev framework callbacks
  646. * ---------------------------------------------------------------------------
  647. */
  648. static int omapfb_open(struct fb_info *fbi, int user)
  649. {
  650. return 0;
  651. }
  652. static int omapfb_release(struct fb_info *fbi, int user)
  653. {
  654. struct omapfb_info *ofbi = FB2OFB(fbi);
  655. struct omapfb2_device *fbdev = ofbi->fbdev;
  656. omapfb_disable_vsync(fbdev);
  657. return 0;
  658. }
  659. static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
  660. const struct fb_fix_screeninfo *fix, int rotation)
  661. {
  662. unsigned offset;
  663. offset = var->yoffset * fix->line_length +
  664. var->xoffset * (var->bits_per_pixel >> 3);
  665. return offset;
  666. }
  667. static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
  668. const struct fb_fix_screeninfo *fix, int rotation)
  669. {
  670. unsigned offset;
  671. if (rotation == FB_ROTATE_UD)
  672. offset = (var->yres_virtual - var->yres) *
  673. fix->line_length;
  674. else if (rotation == FB_ROTATE_CW)
  675. offset = (var->yres_virtual - var->yres) *
  676. (var->bits_per_pixel >> 3);
  677. else
  678. offset = 0;
  679. if (rotation == FB_ROTATE_UR)
  680. offset += var->yoffset * fix->line_length +
  681. var->xoffset * (var->bits_per_pixel >> 3);
  682. else if (rotation == FB_ROTATE_UD)
  683. offset -= var->yoffset * fix->line_length +
  684. var->xoffset * (var->bits_per_pixel >> 3);
  685. else if (rotation == FB_ROTATE_CW)
  686. offset -= var->xoffset * fix->line_length +
  687. var->yoffset * (var->bits_per_pixel >> 3);
  688. else if (rotation == FB_ROTATE_CCW)
  689. offset += var->xoffset * fix->line_length +
  690. var->yoffset * (var->bits_per_pixel >> 3);
  691. return offset;
  692. }
  693. static void omapfb_calc_addr(const struct omapfb_info *ofbi,
  694. const struct fb_var_screeninfo *var,
  695. const struct fb_fix_screeninfo *fix,
  696. int rotation, u32 *paddr, void __iomem **vaddr)
  697. {
  698. u32 data_start_p;
  699. void __iomem *data_start_v;
  700. int offset;
  701. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  702. data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
  703. data_start_v = NULL;
  704. } else {
  705. data_start_p = omapfb_get_region_paddr(ofbi);
  706. data_start_v = omapfb_get_region_vaddr(ofbi);
  707. }
  708. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
  709. offset = calc_rotation_offset_vrfb(var, fix, rotation);
  710. else
  711. offset = calc_rotation_offset_dma(var, fix, rotation);
  712. data_start_p += offset;
  713. data_start_v += offset;
  714. if (offset)
  715. DBG("offset %d, %d = %d\n",
  716. var->xoffset, var->yoffset, offset);
  717. DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
  718. *paddr = data_start_p;
  719. *vaddr = data_start_v;
  720. }
  721. /* setup overlay according to the fb */
  722. int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
  723. u16 posx, u16 posy, u16 outw, u16 outh)
  724. {
  725. int r = 0;
  726. struct omapfb_info *ofbi = FB2OFB(fbi);
  727. struct fb_var_screeninfo *var = &fbi->var;
  728. struct fb_fix_screeninfo *fix = &fbi->fix;
  729. enum omap_color_mode mode = 0;
  730. u32 data_start_p = 0;
  731. void __iomem *data_start_v = NULL;
  732. struct omap_overlay_info info;
  733. int xres, yres;
  734. int screen_width;
  735. int mirror;
  736. int rotation = var->rotate;
  737. int i;
  738. WARN_ON(!atomic_read(&ofbi->region->lock_count));
  739. for (i = 0; i < ofbi->num_overlays; i++) {
  740. if (ovl != ofbi->overlays[i])
  741. continue;
  742. rotation = (rotation + ofbi->rotation[i]) % 4;
  743. break;
  744. }
  745. DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
  746. posx, posy, outw, outh);
  747. if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
  748. xres = var->yres;
  749. yres = var->xres;
  750. } else {
  751. xres = var->xres;
  752. yres = var->yres;
  753. }
  754. if (ofbi->region->size)
  755. omapfb_calc_addr(ofbi, var, fix, rotation,
  756. &data_start_p, &data_start_v);
  757. r = omapfb_mode_to_dss_mode(var, &mode);
  758. if (r) {
  759. DBG("omapfb_mode_to_dss_mode failed");
  760. goto err;
  761. }
  762. switch (var->nonstd) {
  763. case OMAPFB_COLOR_YUV422:
  764. case OMAPFB_COLOR_YUY422:
  765. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  766. screen_width = fix->line_length
  767. / (var->bits_per_pixel >> 2);
  768. break;
  769. }
  770. default:
  771. screen_width = fix->line_length / (var->bits_per_pixel >> 3);
  772. break;
  773. }
  774. ovl->get_overlay_info(ovl, &info);
  775. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
  776. mirror = 0;
  777. else
  778. mirror = ofbi->mirror;
  779. info.paddr = data_start_p;
  780. info.vaddr = data_start_v;
  781. info.screen_width = screen_width;
  782. info.width = xres;
  783. info.height = yres;
  784. info.color_mode = mode;
  785. info.rotation_type = ofbi->rotation_type;
  786. info.rotation = rotation;
  787. info.mirror = mirror;
  788. info.pos_x = posx;
  789. info.pos_y = posy;
  790. info.out_width = outw;
  791. info.out_height = outh;
  792. r = ovl->set_overlay_info(ovl, &info);
  793. if (r) {
  794. DBG("ovl->setup_overlay_info failed\n");
  795. goto err;
  796. }
  797. return 0;
  798. err:
  799. DBG("setup_overlay failed\n");
  800. return r;
  801. }
  802. /* apply var to the overlay */
  803. int omapfb_apply_changes(struct fb_info *fbi, int init)
  804. {
  805. int r = 0;
  806. struct omapfb_info *ofbi = FB2OFB(fbi);
  807. struct fb_var_screeninfo *var = &fbi->var;
  808. struct omap_overlay *ovl;
  809. u16 posx, posy;
  810. u16 outw, outh;
  811. int i;
  812. #ifdef DEBUG
  813. if (omapfb_test_pattern)
  814. fill_fb(fbi);
  815. #endif
  816. WARN_ON(!atomic_read(&ofbi->region->lock_count));
  817. for (i = 0; i < ofbi->num_overlays; i++) {
  818. ovl = ofbi->overlays[i];
  819. DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
  820. if (ofbi->region->size == 0) {
  821. /* the fb is not available. disable the overlay */
  822. omapfb_overlay_enable(ovl, 0);
  823. if (!init && ovl->manager)
  824. ovl->manager->apply(ovl->manager);
  825. continue;
  826. }
  827. if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
  828. int rotation = (var->rotate + ofbi->rotation[i]) % 4;
  829. if (rotation == FB_ROTATE_CW ||
  830. rotation == FB_ROTATE_CCW) {
  831. outw = var->yres;
  832. outh = var->xres;
  833. } else {
  834. outw = var->xres;
  835. outh = var->yres;
  836. }
  837. } else {
  838. outw = ovl->info.out_width;
  839. outh = ovl->info.out_height;
  840. }
  841. if (init) {
  842. posx = 0;
  843. posy = 0;
  844. } else {
  845. posx = ovl->info.pos_x;
  846. posy = ovl->info.pos_y;
  847. }
  848. r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
  849. if (r)
  850. goto err;
  851. if (!init && ovl->manager)
  852. ovl->manager->apply(ovl->manager);
  853. }
  854. return 0;
  855. err:
  856. DBG("apply_changes failed\n");
  857. return r;
  858. }
  859. /* checks var and eventually tweaks it to something supported,
  860. * DO NOT MODIFY PAR */
  861. static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
  862. {
  863. struct omapfb_info *ofbi = FB2OFB(fbi);
  864. int r;
  865. DBG("check_var(%d)\n", FB2OFB(fbi)->id);
  866. omapfb_get_mem_region(ofbi->region);
  867. r = check_fb_var(fbi, var);
  868. omapfb_put_mem_region(ofbi->region);
  869. return r;
  870. }
  871. void omapfb_fb2dss_timings(struct fb_videomode *fb_timings,
  872. struct omap_video_timings *dss_timings)
  873. {
  874. dss_timings->x_res = fb_timings->xres;
  875. dss_timings->y_res = fb_timings->yres;
  876. if (fb_timings->vmode & FB_VMODE_INTERLACED)
  877. dss_timings->y_res /= 2;
  878. dss_timings->pixel_clock = fb_timings->pixclock ?
  879. PICOS2KHZ(fb_timings->pixclock) : 0;
  880. dss_timings->hfp = fb_timings->right_margin;
  881. dss_timings->hbp = fb_timings->left_margin;
  882. dss_timings->hsw = fb_timings->hsync_len;
  883. dss_timings->vfp = fb_timings->lower_margin;
  884. dss_timings->vbp = fb_timings->upper_margin;
  885. dss_timings->vsw = fb_timings->vsync_len;
  886. }
  887. EXPORT_SYMBOL(omapfb_fb2dss_timings);
  888. void omapfb_dss2fb_timings(struct omap_video_timings *dss_timings,
  889. struct fb_videomode *fb_timings)
  890. {
  891. memset(fb_timings, 0, sizeof(*fb_timings));
  892. fb_timings->xres = dss_timings->x_res;
  893. fb_timings->yres = dss_timings->y_res;
  894. fb_timings->pixclock = dss_timings->pixel_clock ?
  895. KHZ2PICOS(dss_timings->pixel_clock) : 0;
  896. fb_timings->right_margin = dss_timings->hfp;
  897. fb_timings->left_margin = dss_timings->hbp;
  898. fb_timings->hsync_len = dss_timings->hsw;
  899. fb_timings->lower_margin = dss_timings->vfp;
  900. fb_timings->upper_margin = dss_timings->vbp;
  901. fb_timings->vsync_len = dss_timings->vsw;
  902. }
  903. EXPORT_SYMBOL(omapfb_dss2fb_timings);
  904. /* set the video mode according to info->var */
  905. static int omapfb_set_par(struct fb_info *fbi)
  906. {
  907. struct omapfb_info *ofbi = FB2OFB(fbi);
  908. int r;
  909. DBG("set_par(%d)\n", FB2OFB(fbi)->id);
  910. omapfb_get_mem_region(ofbi->region);
  911. set_fb_fix(fbi);
  912. r = setup_vrfb_rotation(fbi);
  913. if (r)
  914. goto out;
  915. r = omapfb_apply_changes(fbi, 0);
  916. out:
  917. omapfb_put_mem_region(ofbi->region);
  918. return r;
  919. }
  920. static int omapfb_pan_display(struct fb_var_screeninfo *var,
  921. struct fb_info *fbi)
  922. {
  923. struct omapfb_info *ofbi = FB2OFB(fbi);
  924. struct fb_var_screeninfo new_var;
  925. int r;
  926. DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
  927. if (var->xoffset == fbi->var.xoffset &&
  928. var->yoffset == fbi->var.yoffset)
  929. return 0;
  930. new_var = fbi->var;
  931. new_var.xoffset = var->xoffset;
  932. new_var.yoffset = var->yoffset;
  933. fbi->var = new_var;
  934. omapfb_get_mem_region(ofbi->region);
  935. r = omapfb_apply_changes(fbi, 0);
  936. omapfb_put_mem_region(ofbi->region);
  937. return r;
  938. }
  939. static void mmap_user_open(struct vm_area_struct *vma)
  940. {
  941. struct omapfb2_mem_region *rg = vma->vm_private_data;
  942. omapfb_get_mem_region(rg);
  943. atomic_inc(&rg->map_count);
  944. omapfb_put_mem_region(rg);
  945. }
  946. static void mmap_user_close(struct vm_area_struct *vma)
  947. {
  948. struct omapfb2_mem_region *rg = vma->vm_private_data;
  949. omapfb_get_mem_region(rg);
  950. atomic_dec(&rg->map_count);
  951. omapfb_put_mem_region(rg);
  952. }
  953. static struct vm_operations_struct mmap_user_ops = {
  954. .open = mmap_user_open,
  955. .close = mmap_user_close,
  956. };
  957. static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
  958. {
  959. struct omapfb_info *ofbi = FB2OFB(fbi);
  960. struct fb_fix_screeninfo *fix = &fbi->fix;
  961. struct omapfb2_mem_region *rg;
  962. unsigned long off;
  963. unsigned long start;
  964. u32 len;
  965. int r = -EINVAL;
  966. if (vma->vm_end - vma->vm_start == 0)
  967. return 0;
  968. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  969. return -EINVAL;
  970. off = vma->vm_pgoff << PAGE_SHIFT;
  971. rg = omapfb_get_mem_region(ofbi->region);
  972. start = omapfb_get_region_paddr(ofbi);
  973. len = fix->smem_len;
  974. if (off >= len)
  975. goto error;
  976. if ((vma->vm_end - vma->vm_start + off) > len)
  977. goto error;
  978. off += start;
  979. DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
  980. vma->vm_pgoff = off >> PAGE_SHIFT;
  981. vma->vm_flags |= VM_IO | VM_RESERVED;
  982. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  983. vma->vm_ops = &mmap_user_ops;
  984. vma->vm_private_data = rg;
  985. if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
  986. vma->vm_end - vma->vm_start,
  987. vma->vm_page_prot)) {
  988. r = -EAGAIN;
  989. goto error;
  990. }
  991. /* vm_ops.open won't be called for mmap itself. */
  992. atomic_inc(&rg->map_count);
  993. omapfb_put_mem_region(rg);
  994. return 0;
  995. error:
  996. omapfb_put_mem_region(ofbi->region);
  997. return r;
  998. }
  999. /* Store a single color palette entry into a pseudo palette or the hardware
  1000. * palette if one is available. For now we support only 16bpp and thus store
  1001. * the entry only to the pseudo palette.
  1002. */
  1003. static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
  1004. u_int blue, u_int transp, int update_hw_pal)
  1005. {
  1006. /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
  1007. /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
  1008. struct fb_var_screeninfo *var = &fbi->var;
  1009. int r = 0;
  1010. enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
  1011. /*switch (plane->color_mode) {*/
  1012. switch (mode) {
  1013. case OMAPFB_COLOR_YUV422:
  1014. case OMAPFB_COLOR_YUV420:
  1015. case OMAPFB_COLOR_YUY422:
  1016. r = -EINVAL;
  1017. break;
  1018. case OMAPFB_COLOR_CLUT_8BPP:
  1019. case OMAPFB_COLOR_CLUT_4BPP:
  1020. case OMAPFB_COLOR_CLUT_2BPP:
  1021. case OMAPFB_COLOR_CLUT_1BPP:
  1022. /*
  1023. if (fbdev->ctrl->setcolreg)
  1024. r = fbdev->ctrl->setcolreg(regno, red, green, blue,
  1025. transp, update_hw_pal);
  1026. */
  1027. /* Fallthrough */
  1028. r = -EINVAL;
  1029. break;
  1030. case OMAPFB_COLOR_RGB565:
  1031. case OMAPFB_COLOR_RGB444:
  1032. case OMAPFB_COLOR_RGB24P:
  1033. case OMAPFB_COLOR_RGB24U:
  1034. if (r != 0)
  1035. break;
  1036. if (regno < 16) {
  1037. u16 pal;
  1038. pal = ((red >> (16 - var->red.length)) <<
  1039. var->red.offset) |
  1040. ((green >> (16 - var->green.length)) <<
  1041. var->green.offset) |
  1042. (blue >> (16 - var->blue.length));
  1043. ((u32 *)(fbi->pseudo_palette))[regno] = pal;
  1044. }
  1045. break;
  1046. default:
  1047. BUG();
  1048. }
  1049. return r;
  1050. }
  1051. static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  1052. u_int transp, struct fb_info *info)
  1053. {
  1054. DBG("setcolreg\n");
  1055. return _setcolreg(info, regno, red, green, blue, transp, 1);
  1056. }
  1057. static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
  1058. {
  1059. int count, index, r;
  1060. u16 *red, *green, *blue, *transp;
  1061. u16 trans = 0xffff;
  1062. DBG("setcmap\n");
  1063. red = cmap->red;
  1064. green = cmap->green;
  1065. blue = cmap->blue;
  1066. transp = cmap->transp;
  1067. index = cmap->start;
  1068. for (count = 0; count < cmap->len; count++) {
  1069. if (transp)
  1070. trans = *transp++;
  1071. r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
  1072. count == cmap->len - 1);
  1073. if (r != 0)
  1074. return r;
  1075. }
  1076. return 0;
  1077. }
  1078. static int omapfb_blank(int blank, struct fb_info *fbi)
  1079. {
  1080. struct omapfb_info *ofbi = FB2OFB(fbi);
  1081. struct omapfb2_device *fbdev = ofbi->fbdev;
  1082. struct omap_dss_device *display = fb2display(fbi);
  1083. int r = 0;
  1084. if (!display)
  1085. return -EINVAL;
  1086. omapfb_lock(fbdev);
  1087. switch (blank) {
  1088. case FB_BLANK_UNBLANK:
  1089. if (display->state == OMAP_DSS_DISPLAY_SUSPENDED) {
  1090. if (display->driver->resume)
  1091. r = display->driver->resume(display);
  1092. } else if (display->state == OMAP_DSS_DISPLAY_DISABLED) {
  1093. if (display->driver->enable)
  1094. r = display->driver->enable(display);
  1095. }
  1096. if (fbdev->vsync_active)
  1097. omapfb_enable_vsync(fbdev);
  1098. break;
  1099. case FB_BLANK_NORMAL:
  1100. /* FB_BLANK_NORMAL could be implemented.
  1101. * Needs DSS additions. */
  1102. case FB_BLANK_VSYNC_SUSPEND:
  1103. case FB_BLANK_HSYNC_SUSPEND:
  1104. case FB_BLANK_POWERDOWN:
  1105. if (fbdev->vsync_active)
  1106. omapfb_disable_vsync(fbdev);
  1107. if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
  1108. goto exit;
  1109. if (display->driver->suspend)
  1110. r = display->driver->suspend(display);
  1111. else if (display->driver->disable)
  1112. display->driver->disable(display);
  1113. break;
  1114. default:
  1115. r = -EINVAL;
  1116. }
  1117. exit:
  1118. omapfb_unlock(fbdev);
  1119. return r;
  1120. }
  1121. #if 0
  1122. /* XXX fb_read and fb_write are needed for VRFB */
  1123. ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
  1124. size_t count, loff_t *ppos)
  1125. {
  1126. DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
  1127. /* XXX needed for VRFB */
  1128. return count;
  1129. }
  1130. #endif
  1131. static struct fb_ops omapfb_ops = {
  1132. .owner = THIS_MODULE,
  1133. .fb_open = omapfb_open,
  1134. .fb_release = omapfb_release,
  1135. .fb_fillrect = cfb_fillrect,
  1136. .fb_copyarea = cfb_copyarea,
  1137. .fb_imageblit = cfb_imageblit,
  1138. .fb_blank = omapfb_blank,
  1139. .fb_ioctl = omapfb_ioctl,
  1140. .fb_check_var = omapfb_check_var,
  1141. .fb_set_par = omapfb_set_par,
  1142. .fb_pan_display = omapfb_pan_display,
  1143. .fb_mmap = omapfb_mmap,
  1144. .fb_setcolreg = omapfb_setcolreg,
  1145. .fb_setcmap = omapfb_setcmap,
  1146. /*.fb_write = omapfb_write,*/
  1147. };
  1148. static void omapfb_free_fbmem(struct fb_info *fbi)
  1149. {
  1150. struct omapfb_info *ofbi = FB2OFB(fbi);
  1151. struct omapfb2_device *fbdev = ofbi->fbdev;
  1152. struct omapfb2_mem_region *rg;
  1153. rg = ofbi->region;
  1154. WARN_ON(atomic_read(&rg->map_count));
  1155. if (rg->paddr)
  1156. if (omap_vram_free(rg->paddr, rg->size))
  1157. dev_err(fbdev->dev, "VRAM FREE failed\n");
  1158. if (rg->vaddr)
  1159. iounmap(rg->vaddr);
  1160. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  1161. /* unmap the 0 angle rotation */
  1162. if (rg->vrfb.vaddr[0]) {
  1163. iounmap(rg->vrfb.vaddr[0]);
  1164. omap_vrfb_release_ctx(&rg->vrfb);
  1165. rg->vrfb.vaddr[0] = NULL;
  1166. }
  1167. }
  1168. rg->vaddr = NULL;
  1169. rg->paddr = 0;
  1170. rg->alloc = 0;
  1171. rg->size = 0;
  1172. }
  1173. static void clear_fb_info(struct fb_info *fbi)
  1174. {
  1175. memset(&fbi->var, 0, sizeof(fbi->var));
  1176. memset(&fbi->fix, 0, sizeof(fbi->fix));
  1177. strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
  1178. }
  1179. static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
  1180. {
  1181. int i;
  1182. DBG("free all fbmem\n");
  1183. for (i = 0; i < fbdev->num_fbs; i++) {
  1184. struct fb_info *fbi = fbdev->fbs[i];
  1185. omapfb_free_fbmem(fbi);
  1186. clear_fb_info(fbi);
  1187. }
  1188. return 0;
  1189. }
  1190. static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
  1191. unsigned long paddr)
  1192. {
  1193. struct omapfb_info *ofbi = FB2OFB(fbi);
  1194. struct omapfb2_device *fbdev = ofbi->fbdev;
  1195. struct omapfb2_mem_region *rg;
  1196. void __iomem *vaddr;
  1197. int r;
  1198. rg = ofbi->region;
  1199. rg->paddr = 0;
  1200. rg->vaddr = NULL;
  1201. memset(&rg->vrfb, 0, sizeof rg->vrfb);
  1202. rg->size = 0;
  1203. rg->type = 0;
  1204. rg->alloc = false;
  1205. rg->map = false;
  1206. size = PAGE_ALIGN(size);
  1207. if (!paddr) {
  1208. DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
  1209. r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
  1210. } else {
  1211. DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
  1212. ofbi->id);
  1213. r = omap_vram_reserve(paddr, size);
  1214. }
  1215. if (r) {
  1216. dev_err(fbdev->dev, "failed to allocate framebuffer\n");
  1217. return -ENOMEM;
  1218. }
  1219. if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
  1220. vaddr = ioremap_wc(paddr, size);
  1221. if (!vaddr) {
  1222. dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
  1223. omap_vram_free(paddr, size);
  1224. return -ENOMEM;
  1225. }
  1226. DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
  1227. } else {
  1228. r = omap_vrfb_request_ctx(&rg->vrfb);
  1229. if (r) {
  1230. dev_err(fbdev->dev, "vrfb create ctx failed\n");
  1231. return r;
  1232. }
  1233. vaddr = NULL;
  1234. }
  1235. rg->paddr = paddr;
  1236. rg->vaddr = vaddr;
  1237. rg->size = size;
  1238. rg->alloc = 1;
  1239. return 0;
  1240. }
  1241. /* allocate fbmem using display resolution as reference */
  1242. static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
  1243. unsigned long paddr)
  1244. {
  1245. struct omapfb_info *ofbi = FB2OFB(fbi);
  1246. struct omapfb2_device *fbdev = ofbi->fbdev;
  1247. struct omap_dss_device *display;
  1248. int bytespp;
  1249. display = fb2display(fbi);
  1250. if (!display)
  1251. return 0;
  1252. switch (omapfb_get_recommended_bpp(fbdev, display)) {
  1253. case 16:
  1254. bytespp = 2;
  1255. break;
  1256. case 24:
  1257. bytespp = 4;
  1258. break;
  1259. default:
  1260. bytespp = 4;
  1261. break;
  1262. }
  1263. if (!size) {
  1264. u16 w, h;
  1265. display->driver->get_resolution(display, &w, &h);
  1266. if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
  1267. size = max(omap_vrfb_min_phys_size(w, h, bytespp),
  1268. omap_vrfb_min_phys_size(h, w, bytespp));
  1269. DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
  1270. w * h * bytespp, size);
  1271. } else {
  1272. size = w * h * bytespp;
  1273. }
  1274. }
  1275. if (!size)
  1276. return 0;
  1277. return omapfb_alloc_fbmem(fbi, size, paddr);
  1278. }
  1279. static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
  1280. {
  1281. enum omap_color_mode mode;
  1282. switch (fmt) {
  1283. case OMAPFB_COLOR_RGB565:
  1284. mode = OMAP_DSS_COLOR_RGB16;
  1285. break;
  1286. case OMAPFB_COLOR_YUV422:
  1287. mode = OMAP_DSS_COLOR_YUV2;
  1288. break;
  1289. case OMAPFB_COLOR_CLUT_8BPP:
  1290. mode = OMAP_DSS_COLOR_CLUT8;
  1291. break;
  1292. case OMAPFB_COLOR_CLUT_4BPP:
  1293. mode = OMAP_DSS_COLOR_CLUT4;
  1294. break;
  1295. case OMAPFB_COLOR_CLUT_2BPP:
  1296. mode = OMAP_DSS_COLOR_CLUT2;
  1297. break;
  1298. case OMAPFB_COLOR_CLUT_1BPP:
  1299. mode = OMAP_DSS_COLOR_CLUT1;
  1300. break;
  1301. case OMAPFB_COLOR_RGB444:
  1302. mode = OMAP_DSS_COLOR_RGB12U;
  1303. break;
  1304. case OMAPFB_COLOR_YUY422:
  1305. mode = OMAP_DSS_COLOR_UYVY;
  1306. break;
  1307. case OMAPFB_COLOR_ARGB16:
  1308. mode = OMAP_DSS_COLOR_ARGB16;
  1309. break;
  1310. case OMAPFB_COLOR_RGB24U:
  1311. mode = OMAP_DSS_COLOR_RGB24U;
  1312. break;
  1313. case OMAPFB_COLOR_RGB24P:
  1314. mode = OMAP_DSS_COLOR_RGB24P;
  1315. break;
  1316. case OMAPFB_COLOR_ARGB32:
  1317. mode = OMAP_DSS_COLOR_ARGB32;
  1318. break;
  1319. case OMAPFB_COLOR_RGBA32:
  1320. mode = OMAP_DSS_COLOR_RGBA32;
  1321. break;
  1322. case OMAPFB_COLOR_RGBX32:
  1323. mode = OMAP_DSS_COLOR_RGBX32;
  1324. break;
  1325. default:
  1326. mode = -EINVAL;
  1327. }
  1328. return mode;
  1329. }
  1330. static int omapfb_parse_vram_param(const char *param, int max_entries,
  1331. unsigned long *sizes, unsigned long *paddrs)
  1332. {
  1333. int fbnum;
  1334. unsigned long size;
  1335. unsigned long paddr = 0;
  1336. char *p, *start;
  1337. start = (char *)param;
  1338. while (1) {
  1339. p = start;
  1340. fbnum = simple_strtoul(p, &p, 10);
  1341. if (p == param)
  1342. return -EINVAL;
  1343. if (*p != ':')
  1344. return -EINVAL;
  1345. if (fbnum >= max_entries)
  1346. return -EINVAL;
  1347. size = memparse(p + 1, &p);
  1348. if (!size)
  1349. return -EINVAL;
  1350. paddr = 0;
  1351. if (*p == '@') {
  1352. paddr = simple_strtoul(p + 1, &p, 16);
  1353. if (!paddr)
  1354. return -EINVAL;
  1355. }
  1356. paddrs[fbnum] = paddr;
  1357. sizes[fbnum] = size;
  1358. if (*p == 0)
  1359. break;
  1360. if (*p != ',')
  1361. return -EINVAL;
  1362. ++p;
  1363. start = p;
  1364. }
  1365. return 0;
  1366. }
  1367. static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
  1368. {
  1369. int i, r;
  1370. unsigned long vram_sizes[10];
  1371. unsigned long vram_paddrs[10];
  1372. memset(&vram_sizes, 0, sizeof(vram_sizes));
  1373. memset(&vram_paddrs, 0, sizeof(vram_paddrs));
  1374. if (def_vram && omapfb_parse_vram_param(def_vram, 10,
  1375. vram_sizes, vram_paddrs)) {
  1376. dev_err(fbdev->dev, "failed to parse vram parameter\n");
  1377. memset(&vram_sizes, 0, sizeof(vram_sizes));
  1378. memset(&vram_paddrs, 0, sizeof(vram_paddrs));
  1379. }
  1380. if (fbdev->dev->platform_data) {
  1381. struct omapfb_platform_data *opd;
  1382. opd = fbdev->dev->platform_data;
  1383. for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
  1384. if (!vram_sizes[i]) {
  1385. unsigned long size;
  1386. unsigned long paddr;
  1387. size = opd->mem_desc.region[i].size;
  1388. paddr = opd->mem_desc.region[i].paddr;
  1389. vram_sizes[i] = size;
  1390. vram_paddrs[i] = paddr;
  1391. }
  1392. }
  1393. }
  1394. for (i = 0; i < fbdev->num_fbs; i++) {
  1395. /* allocate memory automatically only for fb0, or if
  1396. * excplicitly defined with vram or plat data option */
  1397. if (i == 0 || vram_sizes[i] != 0) {
  1398. r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
  1399. vram_sizes[i], vram_paddrs[i]);
  1400. if (r)
  1401. return r;
  1402. }
  1403. }
  1404. for (i = 0; i < fbdev->num_fbs; i++) {
  1405. struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
  1406. struct omapfb2_mem_region *rg;
  1407. rg = ofbi->region;
  1408. DBG("region%d phys %08x virt %p size=%lu\n",
  1409. i,
  1410. rg->paddr,
  1411. rg->vaddr,
  1412. rg->size);
  1413. }
  1414. return 0;
  1415. }
  1416. int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
  1417. {
  1418. struct omapfb_info *ofbi = FB2OFB(fbi);
  1419. struct omapfb2_device *fbdev = ofbi->fbdev;
  1420. struct omap_dss_device *display = fb2display(fbi);
  1421. struct omapfb2_mem_region *rg = ofbi->region;
  1422. unsigned long old_size = rg->size;
  1423. unsigned long old_paddr = rg->paddr;
  1424. int old_type = rg->type;
  1425. int r;
  1426. if (type > OMAPFB_MEMTYPE_MAX)
  1427. return -EINVAL;
  1428. size = PAGE_ALIGN(size);
  1429. if (old_size == size && old_type == type)
  1430. return 0;
  1431. if (display && display->driver->sync)
  1432. display->driver->sync(display);
  1433. omapfb_free_fbmem(fbi);
  1434. if (size == 0) {
  1435. clear_fb_info(fbi);
  1436. return 0;
  1437. }
  1438. r = omapfb_alloc_fbmem(fbi, size, 0);
  1439. if (r) {
  1440. if (old_size)
  1441. omapfb_alloc_fbmem(fbi, old_size, old_paddr);
  1442. if (rg->size == 0)
  1443. clear_fb_info(fbi);
  1444. return r;
  1445. }
  1446. if (old_size == size)
  1447. return 0;
  1448. if (old_size == 0) {
  1449. DBG("initializing fb %d\n", ofbi->id);
  1450. r = omapfb_fb_init(fbdev, fbi);
  1451. if (r) {
  1452. DBG("omapfb_fb_init failed\n");
  1453. goto err;
  1454. }
  1455. r = omapfb_apply_changes(fbi, 1);
  1456. if (r) {
  1457. DBG("omapfb_apply_changes failed\n");
  1458. goto err;
  1459. }
  1460. } else {
  1461. struct fb_var_screeninfo new_var;
  1462. memcpy(&new_var, &fbi->var, sizeof(new_var));
  1463. r = check_fb_var(fbi, &new_var);
  1464. if (r)
  1465. goto err;
  1466. memcpy(&fbi->var, &new_var, sizeof(fbi->var));
  1467. set_fb_fix(fbi);
  1468. r = setup_vrfb_rotation(fbi);
  1469. if (r)
  1470. goto err;
  1471. }
  1472. return 0;
  1473. err:
  1474. omapfb_free_fbmem(fbi);
  1475. clear_fb_info(fbi);
  1476. return r;
  1477. }
  1478. /* initialize fb_info, var, fix to something sane based on the display */
  1479. static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
  1480. {
  1481. struct fb_var_screeninfo *var = &fbi->var;
  1482. struct omap_dss_device *display = fb2display(fbi);
  1483. struct omapfb_info *ofbi = FB2OFB(fbi);
  1484. int r = 0;
  1485. fbi->fbops = &omapfb_ops;
  1486. fbi->flags = FBINFO_FLAG_DEFAULT;
  1487. fbi->pseudo_palette = fbdev->pseudo_palette;
  1488. if (ofbi->region->size == 0) {
  1489. clear_fb_info(fbi);
  1490. return 0;
  1491. }
  1492. var->nonstd = 0;
  1493. var->bits_per_pixel = 0;
  1494. var->rotate = def_rotate;
  1495. /*
  1496. * Check if there is a default color format set in the board file,
  1497. * and use this format instead the default deducted from the
  1498. * display bpp.
  1499. */
  1500. if (fbdev->dev->platform_data) {
  1501. struct omapfb_platform_data *opd;
  1502. int id = ofbi->id;
  1503. opd = fbdev->dev->platform_data;
  1504. if (opd->mem_desc.region[id].format_used) {
  1505. enum omap_color_mode mode;
  1506. enum omapfb_color_format format;
  1507. format = opd->mem_desc.region[id].format;
  1508. mode = fb_format_to_dss_mode(format);
  1509. if (mode < 0) {
  1510. r = mode;
  1511. goto err;
  1512. }
  1513. r = dss_mode_to_fb_mode(mode, var);
  1514. if (r < 0)
  1515. goto err;
  1516. }
  1517. }
  1518. if (display) {
  1519. u16 w, h;
  1520. int rotation = (var->rotate + ofbi->rotation[0]) % 4;
  1521. display->driver->get_resolution(display, &w, &h);
  1522. if (rotation == FB_ROTATE_CW ||
  1523. rotation == FB_ROTATE_CCW) {
  1524. var->xres = h;
  1525. var->yres = w;
  1526. } else {
  1527. var->xres = w;
  1528. var->yres = h;
  1529. }
  1530. var->xres_virtual = var->xres;
  1531. var->yres_virtual = var->yres;
  1532. if (!var->bits_per_pixel) {
  1533. switch (omapfb_get_recommended_bpp(fbdev, display)) {
  1534. case 16:
  1535. var->bits_per_pixel = 16;
  1536. break;
  1537. case 24:
  1538. var->bits_per_pixel = 32;
  1539. break;
  1540. default:
  1541. dev_err(fbdev->dev, "illegal display "
  1542. "bpp\n");
  1543. return -EINVAL;
  1544. }
  1545. }
  1546. } else {
  1547. /* if there's no display, let's just guess some basic values */
  1548. var->xres = 320;
  1549. var->yres = 240;
  1550. var->xres_virtual = var->xres;
  1551. var->yres_virtual = var->yres;
  1552. if (!var->bits_per_pixel)
  1553. var->bits_per_pixel = 16;
  1554. }
  1555. r = check_fb_var(fbi, var);
  1556. if (r)
  1557. goto err;
  1558. set_fb_fix(fbi);
  1559. r = setup_vrfb_rotation(fbi);
  1560. if (r)
  1561. goto err;
  1562. r = fb_alloc_cmap(&fbi->cmap, 256, 0);
  1563. if (r)
  1564. dev_err(fbdev->dev, "unable to allocate color map memory\n");
  1565. err:
  1566. return r;
  1567. }
  1568. static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
  1569. {
  1570. fb_dealloc_cmap(&fbi->cmap);
  1571. }
  1572. static void omapfb_free_resources(struct omapfb2_device *fbdev)
  1573. {
  1574. int i;
  1575. DBG("free_resources\n");
  1576. if (fbdev == NULL)
  1577. return;
  1578. for (i = 0; i < fbdev->num_fbs; i++)
  1579. unregister_framebuffer(fbdev->fbs[i]);
  1580. /* free the reserved fbmem */
  1581. omapfb_free_all_fbmem(fbdev);
  1582. for (i = 0; i < fbdev->num_fbs; i++) {
  1583. fbinfo_cleanup(fbdev, fbdev->fbs[i]);
  1584. framebuffer_release(fbdev->fbs[i]);
  1585. }
  1586. for (i = 0; i < fbdev->num_displays; i++) {
  1587. if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
  1588. fbdev->displays[i]->driver->disable(fbdev->displays[i]);
  1589. omap_dss_put_device(fbdev->displays[i]);
  1590. }
  1591. dev_set_drvdata(fbdev->dev, NULL);
  1592. kfree(fbdev);
  1593. }
  1594. static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
  1595. {
  1596. int r, i;
  1597. fbdev->num_fbs = 0;
  1598. DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
  1599. /* allocate fb_infos */
  1600. for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
  1601. struct fb_info *fbi;
  1602. struct omapfb_info *ofbi;
  1603. fbi = framebuffer_alloc(sizeof(struct omapfb_info),
  1604. fbdev->dev);
  1605. if (fbi == NULL) {
  1606. dev_err(fbdev->dev,
  1607. "unable to allocate memory for plane info\n");
  1608. return -ENOMEM;
  1609. }
  1610. clear_fb_info(fbi);
  1611. fbdev->fbs[i] = fbi;
  1612. ofbi = FB2OFB(fbi);
  1613. ofbi->fbdev = fbdev;
  1614. ofbi->id = i;
  1615. ofbi->region = &fbdev->regions[i];
  1616. ofbi->region->id = i;
  1617. init_rwsem(&ofbi->region->lock);
  1618. /* assign these early, so that fb alloc can use them */
  1619. ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
  1620. OMAP_DSS_ROT_DMA;
  1621. ofbi->mirror = def_mirror;
  1622. fbdev->num_fbs++;
  1623. }
  1624. DBG("fb_infos allocated\n");
  1625. /* assign overlays for the fbs */
  1626. for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
  1627. struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
  1628. ofbi->overlays[0] = fbdev->overlays[i];
  1629. ofbi->num_overlays = 1;
  1630. }
  1631. /* allocate fb memories */
  1632. r = omapfb_allocate_all_fbs(fbdev);
  1633. if (r) {
  1634. dev_err(fbdev->dev, "failed to allocate fbmem\n");
  1635. return r;
  1636. }
  1637. DBG("fbmems allocated\n");
  1638. /* setup fb_infos */
  1639. for (i = 0; i < fbdev->num_fbs; i++) {
  1640. struct fb_info *fbi = fbdev->fbs[i];
  1641. struct omapfb_info *ofbi = FB2OFB(fbi);
  1642. omapfb_get_mem_region(ofbi->region);
  1643. r = omapfb_fb_init(fbdev, fbi);
  1644. omapfb_put_mem_region(ofbi->region);
  1645. if (r) {
  1646. dev_err(fbdev->dev, "failed to setup fb_info\n");
  1647. return r;
  1648. }
  1649. }
  1650. DBG("fb_infos initialized\n");
  1651. for (i = 0; i < fbdev->num_fbs; i++) {
  1652. r = register_framebuffer(fbdev->fbs[i]);
  1653. if (r != 0) {
  1654. dev_err(fbdev->dev,
  1655. "registering framebuffer %d failed\n", i);
  1656. return r;
  1657. }
  1658. }
  1659. DBG("framebuffers registered\n");
  1660. for (i = 0; i < fbdev->num_fbs; i++) {
  1661. struct fb_info *fbi = fbdev->fbs[i];
  1662. struct omapfb_info *ofbi = FB2OFB(fbi);
  1663. omapfb_get_mem_region(ofbi->region);
  1664. r = omapfb_apply_changes(fbi, 1);
  1665. omapfb_put_mem_region(ofbi->region);
  1666. if (r) {
  1667. dev_err(fbdev->dev, "failed to change mode\n");
  1668. return r;
  1669. }
  1670. }
  1671. /* Enable fb0 */
  1672. if (fbdev->num_fbs > 0) {
  1673. struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
  1674. if (ofbi->num_overlays > 0) {
  1675. struct omap_overlay *ovl = ofbi->overlays[0];
  1676. r = omapfb_overlay_enable(ovl, 1);
  1677. if (r) {
  1678. dev_err(fbdev->dev,
  1679. "failed to enable overlay\n");
  1680. return r;
  1681. }
  1682. }
  1683. }
  1684. DBG("create_framebuffers done\n");
  1685. return 0;
  1686. }
  1687. static int omapfb_mode_to_timings(const char *mode_str,
  1688. struct omap_video_timings *timings, u8 *bpp)
  1689. {
  1690. struct fb_info *fbi;
  1691. struct fb_var_screeninfo *var;
  1692. struct fb_ops *fbops;
  1693. int r;
  1694. #ifdef CONFIG_OMAP2_DSS_VENC
  1695. if (strcmp(mode_str, "pal") == 0) {
  1696. *timings = omap_dss_pal_timings;
  1697. *bpp = 24;
  1698. return 0;
  1699. } else if (strcmp(mode_str, "ntsc") == 0) {
  1700. *timings = omap_dss_ntsc_timings;
  1701. *bpp = 24;
  1702. return 0;
  1703. }
  1704. #endif
  1705. /* this is quite a hack, but I wanted to use the modedb and for
  1706. * that we need fb_info and var, so we create dummy ones */
  1707. *bpp = 0;
  1708. fbi = NULL;
  1709. var = NULL;
  1710. fbops = NULL;
  1711. fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
  1712. if (fbi == NULL) {
  1713. r = -ENOMEM;
  1714. goto err;
  1715. }
  1716. var = kzalloc(sizeof(*var), GFP_KERNEL);
  1717. if (var == NULL) {
  1718. r = -ENOMEM;
  1719. goto err;
  1720. }
  1721. fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
  1722. if (fbops == NULL) {
  1723. r = -ENOMEM;
  1724. goto err;
  1725. }
  1726. fbi->fbops = fbops;
  1727. r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
  1728. if (r == 0) {
  1729. r = -EINVAL;
  1730. goto err;
  1731. }
  1732. timings->pixel_clock = PICOS2KHZ(var->pixclock);
  1733. timings->hbp = var->left_margin;
  1734. timings->hfp = var->right_margin;
  1735. timings->vbp = var->upper_margin;
  1736. timings->vfp = var->lower_margin;
  1737. timings->hsw = var->hsync_len;
  1738. timings->vsw = var->vsync_len;
  1739. timings->x_res = var->xres;
  1740. timings->y_res = var->yres;
  1741. switch (var->bits_per_pixel) {
  1742. case 16:
  1743. *bpp = 16;
  1744. break;
  1745. case 24:
  1746. case 32:
  1747. default:
  1748. *bpp = 24;
  1749. break;
  1750. }
  1751. r = 0;
  1752. err:
  1753. kfree(fbi);
  1754. kfree(var);
  1755. kfree(fbops);
  1756. return r;
  1757. }
  1758. static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
  1759. struct omap_dss_device *display, char *mode_str)
  1760. {
  1761. int r;
  1762. u8 bpp;
  1763. struct omap_video_timings timings, temp_timings;
  1764. r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
  1765. if (r)
  1766. return r;
  1767. fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
  1768. fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
  1769. ++fbdev->num_bpp_overrides;
  1770. if (display->driver->check_timings) {
  1771. r = display->driver->check_timings(display, &timings);
  1772. if (r)
  1773. return r;
  1774. } else {
  1775. /* If check_timings is not present compare xres and yres */
  1776. if (display->driver->get_timings) {
  1777. display->driver->get_timings(display, &temp_timings);
  1778. if (temp_timings.x_res != timings.x_res ||
  1779. temp_timings.y_res != timings.y_res)
  1780. return -EINVAL;
  1781. }
  1782. }
  1783. if (display->driver->set_timings)
  1784. display->driver->set_timings(display, &timings);
  1785. return 0;
  1786. }
  1787. static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
  1788. struct omap_dss_device *dssdev)
  1789. {
  1790. int i;
  1791. BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
  1792. for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
  1793. if (dssdev == fbdev->bpp_overrides[i].dssdev)
  1794. return fbdev->bpp_overrides[i].bpp;
  1795. }
  1796. return dssdev->driver->get_recommended_bpp(dssdev);
  1797. }
  1798. static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
  1799. {
  1800. char *str, *options, *this_opt;
  1801. int r = 0;
  1802. str = kstrdup(def_mode, GFP_KERNEL);
  1803. if (!str)
  1804. return -ENOMEM;
  1805. options = str;
  1806. while (!r && (this_opt = strsep(&options, ",")) != NULL) {
  1807. char *p, *display_str, *mode_str;
  1808. struct omap_dss_device *display;
  1809. int i;
  1810. p = strchr(this_opt, ':');
  1811. if (!p) {
  1812. r = -EINVAL;
  1813. break;
  1814. }
  1815. *p = 0;
  1816. display_str = this_opt;
  1817. mode_str = p + 1;
  1818. display = NULL;
  1819. for (i = 0; i < fbdev->num_displays; ++i) {
  1820. if (strcmp(fbdev->displays[i]->name,
  1821. display_str) == 0) {
  1822. display = fbdev->displays[i];
  1823. break;
  1824. }
  1825. }
  1826. if (!display) {
  1827. r = -EINVAL;
  1828. break;
  1829. }
  1830. r = omapfb_set_def_mode(fbdev, display, mode_str);
  1831. if (r)
  1832. break;
  1833. }
  1834. kfree(str);
  1835. return r;
  1836. }
  1837. static int omapfb_init_display(struct omapfb2_device *fbdev,
  1838. struct omap_dss_device *dssdev)
  1839. {
  1840. struct omap_dss_driver *dssdrv = dssdev->driver;
  1841. int r;
  1842. r = dssdrv->enable(dssdev);
  1843. if (r) {
  1844. dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
  1845. dssdev->name);
  1846. return r;
  1847. }
  1848. if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
  1849. u16 w, h;
  1850. if (dssdrv->enable_te) {
  1851. r = dssdrv->enable_te(dssdev, 1);
  1852. if (r) {
  1853. dev_err(fbdev->dev, "Failed to set TE\n");
  1854. return r;
  1855. }
  1856. }
  1857. if (dssdrv->set_update_mode) {
  1858. r = dssdrv->set_update_mode(dssdev,
  1859. OMAP_DSS_UPDATE_MANUAL);
  1860. if (r) {
  1861. dev_err(fbdev->dev,
  1862. "Failed to set update mode\n");
  1863. return r;
  1864. }
  1865. }
  1866. dssdrv->get_resolution(dssdev, &w, &h);
  1867. r = dssdrv->update(dssdev, 0, 0, w, h);
  1868. if (r) {
  1869. dev_err(fbdev->dev,
  1870. "Failed to update display\n");
  1871. return r;
  1872. }
  1873. } else {
  1874. if (dssdrv->set_update_mode) {
  1875. r = dssdrv->set_update_mode(dssdev,
  1876. OMAP_DSS_UPDATE_AUTO);
  1877. if (r) {
  1878. dev_err(fbdev->dev,
  1879. "Failed to set update mode\n");
  1880. return r;
  1881. }
  1882. }
  1883. }
  1884. return 0;
  1885. }
  1886. static void omapfb_send_vsync_work(struct work_struct *work)
  1887. {
  1888. struct omapfb2_device *fbdev =
  1889. container_of(work, typeof(*fbdev), vsync_work);
  1890. char buf[64];
  1891. char *envp[2];
  1892. snprintf(buf, sizeof(buf), "VSYNC=%llu",
  1893. ktime_to_ns(fbdev->vsync_timestamp));
  1894. envp[0] = buf;
  1895. envp[1] = NULL;
  1896. kobject_uevent_env(&fbdev->dev->kobj, KOBJ_CHANGE, envp);
  1897. }
  1898. static void omapfb_vsync_isr(void *data, u32 mask)
  1899. {
  1900. struct omapfb2_device *fbdev = data;
  1901. fbdev->vsync_timestamp = ktime_get();
  1902. schedule_work(&fbdev->vsync_work);
  1903. }
  1904. int omapfb_enable_vsync(struct omapfb2_device *fbdev)
  1905. {
  1906. int r;
  1907. /* TODO: should determine correct IRQ like dss_mgr_wait_for_vsync does*/
  1908. r = omap_dispc_register_isr(omapfb_vsync_isr, fbdev, DISPC_IRQ_VSYNC);
  1909. return r;
  1910. }
  1911. void omapfb_disable_vsync(struct omapfb2_device *fbdev)
  1912. {
  1913. omap_dispc_unregister_isr(omapfb_vsync_isr, fbdev, DISPC_IRQ_VSYNC);
  1914. }
  1915. static int omapfb_probe(struct platform_device *pdev)
  1916. {
  1917. struct omapfb2_device *fbdev = NULL;
  1918. int r = 0;
  1919. int i;
  1920. struct omap_overlay *ovl;
  1921. struct omap_dss_device *def_display;
  1922. struct omap_dss_device *dssdev;
  1923. DBG("omapfb_probe\n");
  1924. if (pdev->num_resources != 0) {
  1925. dev_err(&pdev->dev, "probed for an unknown device\n");
  1926. r = -ENODEV;
  1927. goto err0;
  1928. }
  1929. fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
  1930. if (fbdev == NULL) {
  1931. r = -ENOMEM;
  1932. goto err0;
  1933. }
  1934. /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
  1935. * available for OMAP2 and OMAP3
  1936. */
  1937. if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
  1938. def_vrfb = 0;
  1939. dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
  1940. "ignoring the module parameter vrfb=y\n");
  1941. }
  1942. mutex_init(&fbdev->mtx);
  1943. fbdev->dev = &pdev->dev;
  1944. platform_set_drvdata(pdev, fbdev);
  1945. r = 0;
  1946. fbdev->num_displays = 0;
  1947. dssdev = NULL;
  1948. for_each_dss_dev(dssdev) {
  1949. omap_dss_get_device(dssdev);
  1950. if (!dssdev->driver) {
  1951. dev_err(&pdev->dev, "no driver for display\n");
  1952. r = -ENODEV;
  1953. }
  1954. fbdev->displays[fbdev->num_displays++] = dssdev;
  1955. }
  1956. if (r)
  1957. goto cleanup;
  1958. if (fbdev->num_displays == 0) {
  1959. dev_err(&pdev->dev, "no displays\n");
  1960. r = -EINVAL;
  1961. goto cleanup;
  1962. }
  1963. fbdev->num_overlays = omap_dss_get_num_overlays();
  1964. for (i = 0; i < fbdev->num_overlays; i++)
  1965. fbdev->overlays[i] = omap_dss_get_overlay(i);
  1966. fbdev->num_managers = omap_dss_get_num_overlay_managers();
  1967. for (i = 0; i < fbdev->num_managers; i++)
  1968. fbdev->managers[i] = omap_dss_get_overlay_manager(i);
  1969. if (def_mode && strlen(def_mode) > 0) {
  1970. if (omapfb_parse_def_modes(fbdev))
  1971. dev_warn(&pdev->dev, "cannot parse default modes\n");
  1972. }
  1973. r = omapfb_create_framebuffers(fbdev);
  1974. if (r)
  1975. goto cleanup;
  1976. for (i = 0; i < fbdev->num_managers; i++) {
  1977. struct omap_overlay_manager *mgr;
  1978. mgr = fbdev->managers[i];
  1979. r = mgr->apply(mgr);
  1980. if (r)
  1981. dev_warn(fbdev->dev, "failed to apply dispc config\n");
  1982. }
  1983. DBG("mgr->apply'ed\n");
  1984. /* gfx overlay should be the default one. find a display
  1985. * connected to that, and use it as default display */
  1986. ovl = omap_dss_get_overlay(0);
  1987. if (ovl->manager && ovl->manager->device) {
  1988. def_display = ovl->manager->device;
  1989. } else {
  1990. dev_warn(&pdev->dev, "cannot find default display\n");
  1991. def_display = NULL;
  1992. }
  1993. if (def_display) {
  1994. r = omapfb_init_display(fbdev, def_display);
  1995. if (r) {
  1996. dev_err(fbdev->dev,
  1997. "failed to initialize default "
  1998. "display\n");
  1999. goto cleanup;
  2000. }
  2001. }
  2002. DBG("create sysfs for fbs\n");
  2003. r = omapfb_create_sysfs(fbdev);
  2004. if (r) {
  2005. dev_err(fbdev->dev, "failed to create sysfs entries\n");
  2006. goto cleanup;
  2007. }
  2008. INIT_WORK(&fbdev->vsync_work, omapfb_send_vsync_work);
  2009. return 0;
  2010. cleanup:
  2011. omapfb_free_resources(fbdev);
  2012. err0:
  2013. dev_err(&pdev->dev, "failed to setup omapfb\n");
  2014. return r;
  2015. }
  2016. static int omapfb_remove(struct platform_device *pdev)
  2017. {
  2018. struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
  2019. /* FIXME: wait till completion of pending events */
  2020. /* TODO: terminate vsync thread */
  2021. omapfb_remove_sysfs(fbdev);
  2022. omapfb_free_resources(fbdev);
  2023. return 0;
  2024. }
  2025. static struct platform_driver omapfb_driver = {
  2026. .probe = omapfb_probe,
  2027. .remove = omapfb_remove,
  2028. .driver = {
  2029. .name = "omapfb",
  2030. .owner = THIS_MODULE,
  2031. },
  2032. };
  2033. static int __init omapfb_init(void)
  2034. {
  2035. DBG("omapfb_init\n");
  2036. if (platform_driver_register(&omapfb_driver)) {
  2037. printk(KERN_ERR "failed to register omapfb driver\n");
  2038. return -ENODEV;
  2039. }
  2040. return 0;
  2041. }
  2042. static void __exit omapfb_exit(void)
  2043. {
  2044. DBG("omapfb_exit\n");
  2045. platform_driver_unregister(&omapfb_driver);
  2046. }
  2047. module_param_named(mode, def_mode, charp, 0);
  2048. module_param_named(vram, def_vram, charp, 0);
  2049. module_param_named(rotate, def_rotate, int, 0);
  2050. module_param_named(vrfb, def_vrfb, bool, 0);
  2051. module_param_named(mirror, def_mirror, bool, 0);
  2052. /* late_initcall to let panel/ctrl drivers loaded first.
  2053. * I guess better option would be a more dynamic approach,
  2054. * so that omapfb reacts to new panels when they are loaded */
  2055. late_initcall(omapfb_init);
  2056. /*module_init(omapfb_init);*/
  2057. module_exit(omapfb_exit);
  2058. MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
  2059. MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
  2060. MODULE_LICENSE("GPL v2");