intel_fb.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /*
  2. * Copyright © 2007 David Airlie
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. * Authors:
  24. * David Airlie
  25. */
  26. #include <linux/module.h>
  27. #include <linux/kernel.h>
  28. #include <linux/errno.h>
  29. #include <linux/string.h>
  30. #include <linux/mm.h>
  31. #include <linux/tty.h>
  32. #include <linux/slab.h>
  33. #include <linux/sysrq.h>
  34. #include <linux/delay.h>
  35. #include <linux/fb.h>
  36. #include <linux/init.h>
  37. #include "drmP.h"
  38. #include "drm.h"
  39. #include "drm_crtc.h"
  40. #include "intel_drv.h"
  41. #include "i915_drm.h"
  42. #include "i915_drv.h"
  43. struct intelfb_par {
  44. struct drm_device *dev;
  45. struct drm_display_mode *our_mode;
  46. struct intel_framebuffer *intel_fb;
  47. int crtc_count;
  48. /* crtc currently bound to this */
  49. uint32_t crtc_ids[2];
  50. };
  51. static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  52. unsigned blue, unsigned transp,
  53. struct fb_info *info)
  54. {
  55. struct intelfb_par *par = info->par;
  56. struct drm_device *dev = par->dev;
  57. struct drm_crtc *crtc;
  58. int i;
  59. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  60. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  61. struct drm_mode_set *modeset = &intel_crtc->mode_set;
  62. struct drm_framebuffer *fb = modeset->fb;
  63. for (i = 0; i < par->crtc_count; i++)
  64. if (crtc->base.id == par->crtc_ids[i])
  65. break;
  66. if (i == par->crtc_count)
  67. continue;
  68. if (regno > 255)
  69. return 1;
  70. if (fb->depth == 8) {
  71. intel_crtc_fb_gamma_set(crtc, red, green, blue, regno);
  72. return 0;
  73. }
  74. if (regno < 16) {
  75. switch (fb->depth) {
  76. case 15:
  77. fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
  78. ((green & 0xf800) >> 6) |
  79. ((blue & 0xf800) >> 11);
  80. break;
  81. case 16:
  82. fb->pseudo_palette[regno] = (red & 0xf800) |
  83. ((green & 0xfc00) >> 5) |
  84. ((blue & 0xf800) >> 11);
  85. break;
  86. case 24:
  87. case 32:
  88. fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
  89. (green & 0xff00) |
  90. ((blue & 0xff00) >> 8);
  91. break;
  92. }
  93. }
  94. }
  95. return 0;
  96. }
  97. static int intelfb_check_var(struct fb_var_screeninfo *var,
  98. struct fb_info *info)
  99. {
  100. struct intelfb_par *par = info->par;
  101. struct intel_framebuffer *intel_fb = par->intel_fb;
  102. struct drm_framebuffer *fb = &intel_fb->base;
  103. int depth;
  104. if (var->pixclock == -1 || !var->pixclock)
  105. return -EINVAL;
  106. /* Need to resize the fb object !!! */
  107. if (var->xres > fb->width || var->yres > fb->height) {
  108. DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
  109. DRM_ERROR("Need resizing code.\n");
  110. return -EINVAL;
  111. }
  112. switch (var->bits_per_pixel) {
  113. case 16:
  114. depth = (var->green.length == 6) ? 16 : 15;
  115. break;
  116. case 32:
  117. depth = (var->transp.length > 0) ? 32 : 24;
  118. break;
  119. default:
  120. depth = var->bits_per_pixel;
  121. break;
  122. }
  123. switch (depth) {
  124. case 8:
  125. var->red.offset = 0;
  126. var->green.offset = 0;
  127. var->blue.offset = 0;
  128. var->red.length = 8;
  129. var->green.length = 8;
  130. var->blue.length = 8;
  131. var->transp.length = 0;
  132. var->transp.offset = 0;
  133. break;
  134. case 15:
  135. var->red.offset = 10;
  136. var->green.offset = 5;
  137. var->blue.offset = 0;
  138. var->red.length = 5;
  139. var->green.length = 5;
  140. var->blue.length = 5;
  141. var->transp.length = 1;
  142. var->transp.offset = 15;
  143. break;
  144. case 16:
  145. var->red.offset = 11;
  146. var->green.offset = 5;
  147. var->blue.offset = 0;
  148. var->red.length = 5;
  149. var->green.length = 6;
  150. var->blue.length = 5;
  151. var->transp.length = 0;
  152. var->transp.offset = 0;
  153. break;
  154. case 24:
  155. var->red.offset = 16;
  156. var->green.offset = 8;
  157. var->blue.offset = 0;
  158. var->red.length = 8;
  159. var->green.length = 8;
  160. var->blue.length = 8;
  161. var->transp.length = 0;
  162. var->transp.offset = 0;
  163. break;
  164. case 32:
  165. var->red.offset = 16;
  166. var->green.offset = 8;
  167. var->blue.offset = 0;
  168. var->red.length = 8;
  169. var->green.length = 8;
  170. var->blue.length = 8;
  171. var->transp.length = 8;
  172. var->transp.offset = 24;
  173. break;
  174. default:
  175. return -EINVAL;
  176. }
  177. return 0;
  178. }
  179. /* this will let fbcon do the mode init */
  180. /* FIXME: take mode config lock? */
  181. static int intelfb_set_par(struct fb_info *info)
  182. {
  183. struct intelfb_par *par = info->par;
  184. struct drm_device *dev = par->dev;
  185. struct fb_var_screeninfo *var = &info->var;
  186. int i;
  187. DRM_DEBUG("%d %d\n", var->xres, var->pixclock);
  188. if (var->pixclock != -1) {
  189. DRM_ERROR("PIXEL CLCOK SET\n");
  190. return -EINVAL;
  191. } else {
  192. struct drm_crtc *crtc;
  193. int ret;
  194. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  195. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  196. for (i = 0; i < par->crtc_count; i++)
  197. if (crtc->base.id == par->crtc_ids[i])
  198. break;
  199. if (i == par->crtc_count)
  200. continue;
  201. if (crtc->fb == intel_crtc->mode_set.fb) {
  202. mutex_lock(&dev->mode_config.mutex);
  203. ret = crtc->funcs->set_config(&intel_crtc->mode_set);
  204. mutex_unlock(&dev->mode_config.mutex);
  205. if (ret)
  206. return ret;
  207. }
  208. }
  209. return 0;
  210. }
  211. }
  212. static int intelfb_pan_display(struct fb_var_screeninfo *var,
  213. struct fb_info *info)
  214. {
  215. struct intelfb_par *par = info->par;
  216. struct drm_device *dev = par->dev;
  217. struct drm_mode_set *modeset;
  218. struct drm_crtc *crtc;
  219. struct intel_crtc *intel_crtc;
  220. int ret = 0;
  221. int i;
  222. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  223. for (i = 0; i < par->crtc_count; i++)
  224. if (crtc->base.id == par->crtc_ids[i])
  225. break;
  226. if (i == par->crtc_count)
  227. continue;
  228. intel_crtc = to_intel_crtc(crtc);
  229. modeset = &intel_crtc->mode_set;
  230. modeset->x = var->xoffset;
  231. modeset->y = var->yoffset;
  232. if (modeset->num_connectors) {
  233. mutex_lock(&dev->mode_config.mutex);
  234. ret = crtc->funcs->set_config(modeset);
  235. mutex_unlock(&dev->mode_config.mutex);
  236. if (!ret) {
  237. info->var.xoffset = var->xoffset;
  238. info->var.yoffset = var->yoffset;
  239. }
  240. }
  241. }
  242. return ret;
  243. }
  244. static void intelfb_on(struct fb_info *info)
  245. {
  246. struct intelfb_par *par = info->par;
  247. struct drm_device *dev = par->dev;
  248. struct drm_crtc *crtc;
  249. struct drm_encoder *encoder;
  250. int i;
  251. /*
  252. * For each CRTC in this fb, find all associated encoders
  253. * and turn them off, then turn off the CRTC.
  254. */
  255. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  256. struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  257. for (i = 0; i < par->crtc_count; i++)
  258. if (crtc->base.id == par->crtc_ids[i])
  259. break;
  260. crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
  261. /* Found a CRTC on this fb, now find encoders */
  262. list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  263. if (encoder->crtc == crtc) {
  264. struct drm_encoder_helper_funcs *encoder_funcs;
  265. encoder_funcs = encoder->helper_private;
  266. encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
  267. }
  268. }
  269. }
  270. }
  271. static void intelfb_off(struct fb_info *info, int dpms_mode)
  272. {
  273. struct intelfb_par *par = info->par;
  274. struct drm_device *dev = par->dev;
  275. struct drm_crtc *crtc;
  276. struct drm_encoder *encoder;
  277. int i;
  278. /*
  279. * For each CRTC in this fb, find all associated encoders
  280. * and turn them off, then turn off the CRTC.
  281. */
  282. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  283. struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  284. for (i = 0; i < par->crtc_count; i++)
  285. if (crtc->base.id == par->crtc_ids[i])
  286. break;
  287. /* Found a CRTC on this fb, now find encoders */
  288. list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  289. if (encoder->crtc == crtc) {
  290. struct drm_encoder_helper_funcs *encoder_funcs;
  291. encoder_funcs = encoder->helper_private;
  292. encoder_funcs->dpms(encoder, dpms_mode);
  293. }
  294. }
  295. if (dpms_mode == DRM_MODE_DPMS_OFF)
  296. crtc_funcs->dpms(crtc, dpms_mode);
  297. }
  298. }
  299. static int intelfb_blank(int blank, struct fb_info *info)
  300. {
  301. switch (blank) {
  302. case FB_BLANK_UNBLANK:
  303. intelfb_on(info);
  304. break;
  305. case FB_BLANK_NORMAL:
  306. intelfb_off(info, DRM_MODE_DPMS_STANDBY);
  307. break;
  308. case FB_BLANK_HSYNC_SUSPEND:
  309. intelfb_off(info, DRM_MODE_DPMS_STANDBY);
  310. break;
  311. case FB_BLANK_VSYNC_SUSPEND:
  312. intelfb_off(info, DRM_MODE_DPMS_SUSPEND);
  313. break;
  314. case FB_BLANK_POWERDOWN:
  315. intelfb_off(info, DRM_MODE_DPMS_OFF);
  316. break;
  317. }
  318. return 0;
  319. }
  320. static struct fb_ops intelfb_ops = {
  321. .owner = THIS_MODULE,
  322. .fb_check_var = intelfb_check_var,
  323. .fb_set_par = intelfb_set_par,
  324. .fb_setcolreg = intelfb_setcolreg,
  325. .fb_fillrect = cfb_fillrect,
  326. .fb_copyarea = cfb_copyarea,
  327. .fb_imageblit = cfb_imageblit,
  328. .fb_pan_display = intelfb_pan_display,
  329. .fb_blank = intelfb_blank,
  330. };
  331. /**
  332. * Curretly it is assumed that the old framebuffer is reused.
  333. *
  334. * LOCKING
  335. * caller should hold the mode config lock.
  336. *
  337. */
  338. int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
  339. {
  340. struct fb_info *info;
  341. struct drm_framebuffer *fb;
  342. struct drm_display_mode *mode = crtc->desired_mode;
  343. fb = crtc->fb;
  344. if (!fb)
  345. return 1;
  346. info = fb->fbdev;
  347. if (!info)
  348. return 1;
  349. if (!mode)
  350. return 1;
  351. info->var.xres = mode->hdisplay;
  352. info->var.right_margin = mode->hsync_start - mode->hdisplay;
  353. info->var.hsync_len = mode->hsync_end - mode->hsync_start;
  354. info->var.left_margin = mode->htotal - mode->hsync_end;
  355. info->var.yres = mode->vdisplay;
  356. info->var.lower_margin = mode->vsync_start - mode->vdisplay;
  357. info->var.vsync_len = mode->vsync_end - mode->vsync_start;
  358. info->var.upper_margin = mode->vtotal - mode->vsync_end;
  359. info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
  360. /* avoid overflow */
  361. info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
  362. return 0;
  363. }
  364. EXPORT_SYMBOL(intelfb_resize);
  365. static struct drm_mode_set kernelfb_mode;
  366. static int intelfb_panic(struct notifier_block *n, unsigned long ununsed,
  367. void *panic_str)
  368. {
  369. DRM_ERROR("panic occurred, switching back to text console\n");
  370. intelfb_restore();
  371. return 0;
  372. }
  373. static struct notifier_block paniced = {
  374. .notifier_call = intelfb_panic,
  375. };
  376. static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
  377. uint32_t fb_height, uint32_t surface_width,
  378. uint32_t surface_height,
  379. struct intel_framebuffer **intel_fb_p)
  380. {
  381. struct fb_info *info;
  382. struct intelfb_par *par;
  383. struct drm_framebuffer *fb;
  384. struct intel_framebuffer *intel_fb;
  385. struct drm_mode_fb_cmd mode_cmd;
  386. struct drm_gem_object *fbo = NULL;
  387. struct drm_i915_gem_object *obj_priv;
  388. struct device *device = &dev->pdev->dev;
  389. int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1;
  390. mode_cmd.width = surface_width;
  391. mode_cmd.height = surface_height;
  392. mode_cmd.bpp = 32;
  393. mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
  394. mode_cmd.depth = 24;
  395. size = mode_cmd.pitch * mode_cmd.height;
  396. size = ALIGN(size, PAGE_SIZE);
  397. fbo = drm_gem_object_alloc(dev, size);
  398. if (!fbo) {
  399. printk(KERN_ERR "failed to allocate framebuffer\n");
  400. ret = -ENOMEM;
  401. goto out;
  402. }
  403. obj_priv = fbo->driver_private;
  404. mutex_lock(&dev->struct_mutex);
  405. ret = i915_gem_object_pin(fbo, PAGE_SIZE);
  406. if (ret) {
  407. DRM_ERROR("failed to pin fb: %d\n", ret);
  408. goto out_unref;
  409. }
  410. /* Flush everything out, we'll be doing GTT only from now on */
  411. i915_gem_object_set_to_gtt_domain(fbo, 1);
  412. ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
  413. if (ret) {
  414. DRM_ERROR("failed to allocate fb.\n");
  415. goto out_unref;
  416. }
  417. list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
  418. intel_fb = to_intel_framebuffer(fb);
  419. *intel_fb_p = intel_fb;
  420. info = framebuffer_alloc(sizeof(struct intelfb_par), device);
  421. if (!info) {
  422. ret = -ENOMEM;
  423. goto out_unref;
  424. }
  425. par = info->par;
  426. strcpy(info->fix.id, "inteldrmfb");
  427. info->fix.type = FB_TYPE_PACKED_PIXELS;
  428. info->fix.visual = FB_VISUAL_TRUECOLOR;
  429. info->fix.type_aux = 0;
  430. info->fix.xpanstep = 1; /* doing it in hw */
  431. info->fix.ypanstep = 1; /* doing it in hw */
  432. info->fix.ywrapstep = 0;
  433. info->fix.accel = FB_ACCEL_I830;
  434. info->fix.type_aux = 0;
  435. info->flags = FBINFO_DEFAULT;
  436. info->fbops = &intelfb_ops;
  437. info->fix.line_length = fb->pitch;
  438. info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
  439. info->fix.smem_len = size;
  440. info->flags = FBINFO_DEFAULT;
  441. info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset,
  442. size);
  443. if (!info->screen_base) {
  444. ret = -ENOSPC;
  445. goto out_unref;
  446. }
  447. info->screen_size = size;
  448. // memset(info->screen_base, 0, size);
  449. info->pseudo_palette = fb->pseudo_palette;
  450. info->var.xres_virtual = fb->width;
  451. info->var.yres_virtual = fb->height;
  452. info->var.bits_per_pixel = fb->bits_per_pixel;
  453. info->var.xoffset = 0;
  454. info->var.yoffset = 0;
  455. info->var.activate = FB_ACTIVATE_NOW;
  456. info->var.height = -1;
  457. info->var.width = -1;
  458. info->var.xres = fb_width;
  459. info->var.yres = fb_height;
  460. /* FIXME: we really shouldn't expose mmio space at all */
  461. info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar);
  462. info->fix.mmio_len = pci_resource_len(dev->pdev, mmio_bar);
  463. info->pixmap.size = 64*1024;
  464. info->pixmap.buf_align = 8;
  465. info->pixmap.access_align = 32;
  466. info->pixmap.flags = FB_PIXMAP_SYSTEM;
  467. info->pixmap.scan_align = 1;
  468. switch(fb->depth) {
  469. case 8:
  470. info->var.red.offset = 0;
  471. info->var.green.offset = 0;
  472. info->var.blue.offset = 0;
  473. info->var.red.length = 8; /* 8bit DAC */
  474. info->var.green.length = 8;
  475. info->var.blue.length = 8;
  476. info->var.transp.offset = 0;
  477. info->var.transp.length = 0;
  478. break;
  479. case 15:
  480. info->var.red.offset = 10;
  481. info->var.green.offset = 5;
  482. info->var.blue.offset = 0;
  483. info->var.red.length = 5;
  484. info->var.green.length = 5;
  485. info->var.blue.length = 5;
  486. info->var.transp.offset = 15;
  487. info->var.transp.length = 1;
  488. break;
  489. case 16:
  490. info->var.red.offset = 11;
  491. info->var.green.offset = 5;
  492. info->var.blue.offset = 0;
  493. info->var.red.length = 5;
  494. info->var.green.length = 6;
  495. info->var.blue.length = 5;
  496. info->var.transp.offset = 0;
  497. break;
  498. case 24:
  499. info->var.red.offset = 16;
  500. info->var.green.offset = 8;
  501. info->var.blue.offset = 0;
  502. info->var.red.length = 8;
  503. info->var.green.length = 8;
  504. info->var.blue.length = 8;
  505. info->var.transp.offset = 0;
  506. info->var.transp.length = 0;
  507. break;
  508. case 32:
  509. info->var.red.offset = 16;
  510. info->var.green.offset = 8;
  511. info->var.blue.offset = 0;
  512. info->var.red.length = 8;
  513. info->var.green.length = 8;
  514. info->var.blue.length = 8;
  515. info->var.transp.offset = 24;
  516. info->var.transp.length = 8;
  517. break;
  518. default:
  519. break;
  520. }
  521. fb->fbdev = info;
  522. par->intel_fb = intel_fb;
  523. par->dev = dev;
  524. /* To allow resizeing without swapping buffers */
  525. printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
  526. intel_fb->base.height, obj_priv->gtt_offset, fbo);
  527. mutex_unlock(&dev->struct_mutex);
  528. return 0;
  529. out_unref:
  530. drm_gem_object_unreference(fbo);
  531. mutex_unlock(&dev->struct_mutex);
  532. out:
  533. return ret;
  534. }
  535. static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
  536. {
  537. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  538. struct intel_framebuffer *intel_fb;
  539. struct drm_framebuffer *fb;
  540. struct drm_connector *connector;
  541. struct fb_info *info;
  542. struct intelfb_par *par;
  543. struct drm_mode_set *modeset;
  544. unsigned int width, height;
  545. int new_fb = 0;
  546. int ret, i, conn_count;
  547. if (!drm_helper_crtc_in_use(crtc))
  548. return 0;
  549. if (!crtc->desired_mode)
  550. return 0;
  551. width = crtc->desired_mode->hdisplay;
  552. height = crtc->desired_mode->vdisplay;
  553. /* is there an fb bound to this crtc already */
  554. if (!intel_crtc->mode_set.fb) {
  555. ret = intelfb_create(dev, width, height, width, height, &intel_fb);
  556. if (ret)
  557. return -EINVAL;
  558. new_fb = 1;
  559. } else {
  560. fb = intel_crtc->mode_set.fb;
  561. intel_fb = to_intel_framebuffer(fb);
  562. if ((intel_fb->base.width < width) || (intel_fb->base.height < height))
  563. return -EINVAL;
  564. }
  565. info = intel_fb->base.fbdev;
  566. par = info->par;
  567. modeset = &intel_crtc->mode_set;
  568. modeset->fb = &intel_fb->base;
  569. conn_count = 0;
  570. list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  571. if (connector->encoder)
  572. if (connector->encoder->crtc == modeset->crtc) {
  573. modeset->connectors[conn_count] = connector;
  574. conn_count++;
  575. if (conn_count > INTELFB_CONN_LIMIT)
  576. BUG();
  577. }
  578. }
  579. for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
  580. modeset->connectors[i] = NULL;
  581. par->crtc_ids[0] = crtc->base.id;
  582. modeset->num_connectors = conn_count;
  583. if (modeset->mode != modeset->crtc->desired_mode)
  584. modeset->mode = modeset->crtc->desired_mode;
  585. par->crtc_count = 1;
  586. if (new_fb) {
  587. info->var.pixclock = -1;
  588. if (register_framebuffer(info) < 0)
  589. return -EINVAL;
  590. } else
  591. intelfb_set_par(info);
  592. printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
  593. info->fix.id);
  594. /* Switch back to kernel console on panic */
  595. kernelfb_mode = *modeset;
  596. atomic_notifier_chain_register(&panic_notifier_list, &paniced);
  597. printk(KERN_INFO "registered panic notifier\n");
  598. return 0;
  599. }
  600. static int intelfb_multi_fb_probe(struct drm_device *dev)
  601. {
  602. struct drm_crtc *crtc;
  603. int ret = 0;
  604. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  605. ret = intelfb_multi_fb_probe_crtc(dev, crtc);
  606. if (ret)
  607. return ret;
  608. }
  609. return ret;
  610. }
  611. static int intelfb_single_fb_probe(struct drm_device *dev)
  612. {
  613. struct drm_crtc *crtc;
  614. struct drm_connector *connector;
  615. unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
  616. unsigned int surface_width = 0, surface_height = 0;
  617. int new_fb = 0;
  618. int crtc_count = 0;
  619. int ret, i, conn_count = 0;
  620. struct intel_framebuffer *intel_fb;
  621. struct fb_info *info;
  622. struct intelfb_par *par;
  623. struct drm_mode_set *modeset = NULL;
  624. DRM_DEBUG("\n");
  625. /* Get a count of crtcs now in use and new min/maxes width/heights */
  626. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  627. if (!drm_helper_crtc_in_use(crtc))
  628. continue;
  629. crtc_count++;
  630. if (!crtc->desired_mode)
  631. continue;
  632. /* Smallest mode determines console size... */
  633. if (crtc->desired_mode->hdisplay < fb_width)
  634. fb_width = crtc->desired_mode->hdisplay;
  635. if (crtc->desired_mode->vdisplay < fb_height)
  636. fb_height = crtc->desired_mode->vdisplay;
  637. /* ... but largest for memory allocation dimensions */
  638. if (crtc->desired_mode->hdisplay > surface_width)
  639. surface_width = crtc->desired_mode->hdisplay;
  640. if (crtc->desired_mode->vdisplay > surface_height)
  641. surface_height = crtc->desired_mode->vdisplay;
  642. }
  643. if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
  644. /* hmm everyone went away - assume VGA cable just fell out
  645. and will come back later. */
  646. DRM_DEBUG("no CRTCs available?\n");
  647. return 0;
  648. }
  649. //fail
  650. /* Find the fb for our new config */
  651. if (list_empty(&dev->mode_config.fb_kernel_list)) {
  652. DRM_DEBUG("creating new fb (console size %dx%d, "
  653. "buffer size %dx%d)\n", fb_width, fb_height,
  654. surface_width, surface_height);
  655. ret = intelfb_create(dev, fb_width, fb_height, surface_width,
  656. surface_height, &intel_fb);
  657. if (ret)
  658. return -EINVAL;
  659. new_fb = 1;
  660. } else {
  661. struct drm_framebuffer *fb;
  662. fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  663. struct drm_framebuffer, filp_head);
  664. intel_fb = to_intel_framebuffer(fb);
  665. /* if someone hotplugs something bigger than we have already
  666. * allocated, we are pwned. As really we can't resize an
  667. * fbdev that is in the wild currently due to fbdev not really
  668. * being designed for the lower layers moving stuff around
  669. * under it.
  670. * - so in the grand style of things - punt.
  671. */
  672. if ((fb->width < surface_width) ||
  673. (fb->height < surface_height)) {
  674. DRM_ERROR("fb not large enough for console\n");
  675. return -EINVAL;
  676. }
  677. }
  678. // fail
  679. info = intel_fb->base.fbdev;
  680. par = info->par;
  681. crtc_count = 0;
  682. /*
  683. * For each CRTC, set up the connector list for the CRTC's mode
  684. * set configuration.
  685. */
  686. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  687. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  688. modeset = &intel_crtc->mode_set;
  689. modeset->fb = &intel_fb->base;
  690. conn_count = 0;
  691. list_for_each_entry(connector, &dev->mode_config.connector_list,
  692. head) {
  693. if (!connector->encoder)
  694. continue;
  695. if(connector->encoder->crtc == modeset->crtc) {
  696. modeset->connectors[conn_count++] = connector;
  697. if (conn_count > INTELFB_CONN_LIMIT)
  698. BUG();
  699. }
  700. }
  701. /* Zero out remaining connector pointers */
  702. for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
  703. modeset->connectors[i] = NULL;
  704. par->crtc_ids[crtc_count++] = crtc->base.id;
  705. modeset->num_connectors = conn_count;
  706. if (modeset->mode != modeset->crtc->desired_mode)
  707. modeset->mode = modeset->crtc->desired_mode;
  708. }
  709. par->crtc_count = crtc_count;
  710. if (new_fb) {
  711. info->var.pixclock = -1;
  712. if (register_framebuffer(info) < 0)
  713. return -EINVAL;
  714. } else
  715. intelfb_set_par(info);
  716. printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
  717. info->fix.id);
  718. /* Switch back to kernel console on panic */
  719. kernelfb_mode = *modeset;
  720. atomic_notifier_chain_register(&panic_notifier_list, &paniced);
  721. printk(KERN_INFO "registered panic notifier\n");
  722. return 0;
  723. }
  724. /**
  725. * intelfb_restore - restore the framebuffer console (kernel) config
  726. *
  727. * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
  728. */
  729. void intelfb_restore(void)
  730. {
  731. drm_crtc_helper_set_config(&kernelfb_mode);
  732. }
  733. static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
  734. {
  735. intelfb_restore();
  736. }
  737. static struct sysrq_key_op sysrq_intelfb_restore_op = {
  738. .handler = intelfb_sysrq,
  739. .help_msg = "force fb",
  740. .action_msg = "force restore of fb console",
  741. };
  742. int intelfb_probe(struct drm_device *dev)
  743. {
  744. int ret;
  745. DRM_DEBUG("\n");
  746. /* something has changed in the lower levels of hell - deal with it
  747. here */
  748. /* two modes : a) 1 fb to rule all crtcs.
  749. b) one fb per crtc.
  750. two actions 1) new connected device
  751. 2) device removed.
  752. case a/1 : if the fb surface isn't big enough - resize the surface fb.
  753. if the fb size isn't big enough - resize fb into surface.
  754. if everything big enough configure the new crtc/etc.
  755. case a/2 : undo the configuration
  756. possibly resize down the fb to fit the new configuration.
  757. case b/1 : see if it is on a new crtc - setup a new fb and add it.
  758. case b/2 : teardown the new fb.
  759. */
  760. /* mode a first */
  761. /* search for an fb */
  762. if (i915_fbpercrtc == 1) {
  763. ret = intelfb_multi_fb_probe(dev);
  764. } else {
  765. ret = intelfb_single_fb_probe(dev);
  766. }
  767. register_sysrq_key('g', &sysrq_intelfb_restore_op);
  768. return ret;
  769. }
  770. EXPORT_SYMBOL(intelfb_probe);
  771. int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
  772. {
  773. struct fb_info *info;
  774. if (!fb)
  775. return -EINVAL;
  776. info = fb->fbdev;
  777. if (info) {
  778. unregister_framebuffer(info);
  779. iounmap(info->screen_base);
  780. framebuffer_release(info);
  781. }
  782. atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
  783. memset(&kernelfb_mode, 0, sizeof(struct drm_mode_set));
  784. return 0;
  785. }
  786. EXPORT_SYMBOL(intelfb_remove);
  787. MODULE_LICENSE("GPL and additional rights");