intel_fb.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  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 CLOCK 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. DRM_ERROR("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_unpin;
  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_unpin;
  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. /* setup aperture base/size for vesafb takeover */
  439. info->aperture_base = dev->mode_config.fb_base;
  440. if (IS_I9XX(dev))
  441. info->aperture_size = pci_resource_len(dev->pdev, 2);
  442. else
  443. info->aperture_size = pci_resource_len(dev->pdev, 0);
  444. info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
  445. info->fix.smem_len = size;
  446. info->flags = FBINFO_DEFAULT;
  447. info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset,
  448. size);
  449. if (!info->screen_base) {
  450. ret = -ENOSPC;
  451. goto out_unpin;
  452. }
  453. info->screen_size = size;
  454. // memset(info->screen_base, 0, size);
  455. info->pseudo_palette = fb->pseudo_palette;
  456. info->var.xres_virtual = fb->width;
  457. info->var.yres_virtual = fb->height;
  458. info->var.bits_per_pixel = fb->bits_per_pixel;
  459. info->var.xoffset = 0;
  460. info->var.yoffset = 0;
  461. info->var.activate = FB_ACTIVATE_NOW;
  462. info->var.height = -1;
  463. info->var.width = -1;
  464. info->var.xres = fb_width;
  465. info->var.yres = fb_height;
  466. /* FIXME: we really shouldn't expose mmio space at all */
  467. info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar);
  468. info->fix.mmio_len = pci_resource_len(dev->pdev, mmio_bar);
  469. info->pixmap.size = 64*1024;
  470. info->pixmap.buf_align = 8;
  471. info->pixmap.access_align = 32;
  472. info->pixmap.flags = FB_PIXMAP_SYSTEM;
  473. info->pixmap.scan_align = 1;
  474. switch(fb->depth) {
  475. case 8:
  476. info->var.red.offset = 0;
  477. info->var.green.offset = 0;
  478. info->var.blue.offset = 0;
  479. info->var.red.length = 8; /* 8bit DAC */
  480. info->var.green.length = 8;
  481. info->var.blue.length = 8;
  482. info->var.transp.offset = 0;
  483. info->var.transp.length = 0;
  484. break;
  485. case 15:
  486. info->var.red.offset = 10;
  487. info->var.green.offset = 5;
  488. info->var.blue.offset = 0;
  489. info->var.red.length = 5;
  490. info->var.green.length = 5;
  491. info->var.blue.length = 5;
  492. info->var.transp.offset = 15;
  493. info->var.transp.length = 1;
  494. break;
  495. case 16:
  496. info->var.red.offset = 11;
  497. info->var.green.offset = 5;
  498. info->var.blue.offset = 0;
  499. info->var.red.length = 5;
  500. info->var.green.length = 6;
  501. info->var.blue.length = 5;
  502. info->var.transp.offset = 0;
  503. break;
  504. case 24:
  505. info->var.red.offset = 16;
  506. info->var.green.offset = 8;
  507. info->var.blue.offset = 0;
  508. info->var.red.length = 8;
  509. info->var.green.length = 8;
  510. info->var.blue.length = 8;
  511. info->var.transp.offset = 0;
  512. info->var.transp.length = 0;
  513. break;
  514. case 32:
  515. info->var.red.offset = 16;
  516. info->var.green.offset = 8;
  517. info->var.blue.offset = 0;
  518. info->var.red.length = 8;
  519. info->var.green.length = 8;
  520. info->var.blue.length = 8;
  521. info->var.transp.offset = 24;
  522. info->var.transp.length = 8;
  523. break;
  524. default:
  525. break;
  526. }
  527. fb->fbdev = info;
  528. par->intel_fb = intel_fb;
  529. par->dev = dev;
  530. /* To allow resizeing without swapping buffers */
  531. DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
  532. intel_fb->base.height, obj_priv->gtt_offset, fbo);
  533. mutex_unlock(&dev->struct_mutex);
  534. return 0;
  535. out_unpin:
  536. i915_gem_object_unpin(fbo);
  537. out_unref:
  538. drm_gem_object_unreference(fbo);
  539. mutex_unlock(&dev->struct_mutex);
  540. out:
  541. return ret;
  542. }
  543. static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
  544. {
  545. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  546. struct intel_framebuffer *intel_fb;
  547. struct drm_framebuffer *fb;
  548. struct drm_connector *connector;
  549. struct fb_info *info;
  550. struct intelfb_par *par;
  551. struct drm_mode_set *modeset;
  552. unsigned int width, height;
  553. int new_fb = 0;
  554. int ret, i, conn_count;
  555. if (!drm_helper_crtc_in_use(crtc))
  556. return 0;
  557. if (!crtc->desired_mode)
  558. return 0;
  559. width = crtc->desired_mode->hdisplay;
  560. height = crtc->desired_mode->vdisplay;
  561. /* is there an fb bound to this crtc already */
  562. if (!intel_crtc->mode_set.fb) {
  563. ret = intelfb_create(dev, width, height, width, height, &intel_fb);
  564. if (ret)
  565. return -EINVAL;
  566. new_fb = 1;
  567. } else {
  568. fb = intel_crtc->mode_set.fb;
  569. intel_fb = to_intel_framebuffer(fb);
  570. if ((intel_fb->base.width < width) || (intel_fb->base.height < height))
  571. return -EINVAL;
  572. }
  573. info = intel_fb->base.fbdev;
  574. par = info->par;
  575. modeset = &intel_crtc->mode_set;
  576. modeset->fb = &intel_fb->base;
  577. conn_count = 0;
  578. list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  579. if (connector->encoder)
  580. if (connector->encoder->crtc == modeset->crtc) {
  581. modeset->connectors[conn_count] = connector;
  582. conn_count++;
  583. if (conn_count > INTELFB_CONN_LIMIT)
  584. BUG();
  585. }
  586. }
  587. for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
  588. modeset->connectors[i] = NULL;
  589. par->crtc_ids[0] = crtc->base.id;
  590. modeset->num_connectors = conn_count;
  591. if (modeset->crtc->desired_mode) {
  592. if (modeset->mode)
  593. drm_mode_destroy(dev, modeset->mode);
  594. modeset->mode = drm_mode_duplicate(dev,
  595. modeset->crtc->desired_mode);
  596. }
  597. par->crtc_count = 1;
  598. if (new_fb) {
  599. info->var.pixclock = -1;
  600. if (register_framebuffer(info) < 0)
  601. return -EINVAL;
  602. } else
  603. intelfb_set_par(info);
  604. DRM_INFO("fb%d: %s frame buffer device\n", info->node,
  605. info->fix.id);
  606. /* Switch back to kernel console on panic */
  607. kernelfb_mode = *modeset;
  608. atomic_notifier_chain_register(&panic_notifier_list, &paniced);
  609. DRM_DEBUG("registered panic notifier\n");
  610. return 0;
  611. }
  612. static int intelfb_multi_fb_probe(struct drm_device *dev)
  613. {
  614. struct drm_crtc *crtc;
  615. int ret = 0;
  616. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  617. ret = intelfb_multi_fb_probe_crtc(dev, crtc);
  618. if (ret)
  619. return ret;
  620. }
  621. return ret;
  622. }
  623. static int intelfb_single_fb_probe(struct drm_device *dev)
  624. {
  625. struct drm_crtc *crtc;
  626. struct drm_connector *connector;
  627. unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
  628. unsigned int surface_width = 0, surface_height = 0;
  629. int new_fb = 0;
  630. int crtc_count = 0;
  631. int ret, i, conn_count = 0;
  632. struct intel_framebuffer *intel_fb;
  633. struct fb_info *info;
  634. struct intelfb_par *par;
  635. struct drm_mode_set *modeset = NULL;
  636. DRM_DEBUG("\n");
  637. /* Get a count of crtcs now in use and new min/maxes width/heights */
  638. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  639. if (!drm_helper_crtc_in_use(crtc))
  640. continue;
  641. crtc_count++;
  642. if (!crtc->desired_mode)
  643. continue;
  644. /* Smallest mode determines console size... */
  645. if (crtc->desired_mode->hdisplay < fb_width)
  646. fb_width = crtc->desired_mode->hdisplay;
  647. if (crtc->desired_mode->vdisplay < fb_height)
  648. fb_height = crtc->desired_mode->vdisplay;
  649. /* ... but largest for memory allocation dimensions */
  650. if (crtc->desired_mode->hdisplay > surface_width)
  651. surface_width = crtc->desired_mode->hdisplay;
  652. if (crtc->desired_mode->vdisplay > surface_height)
  653. surface_height = crtc->desired_mode->vdisplay;
  654. }
  655. if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
  656. /* hmm everyone went away - assume VGA cable just fell out
  657. and will come back later. */
  658. DRM_DEBUG("no CRTCs available?\n");
  659. return 0;
  660. }
  661. //fail
  662. /* Find the fb for our new config */
  663. if (list_empty(&dev->mode_config.fb_kernel_list)) {
  664. DRM_DEBUG("creating new fb (console size %dx%d, "
  665. "buffer size %dx%d)\n", fb_width, fb_height,
  666. surface_width, surface_height);
  667. ret = intelfb_create(dev, fb_width, fb_height, surface_width,
  668. surface_height, &intel_fb);
  669. if (ret)
  670. return -EINVAL;
  671. new_fb = 1;
  672. } else {
  673. struct drm_framebuffer *fb;
  674. fb = list_first_entry(&dev->mode_config.fb_kernel_list,
  675. struct drm_framebuffer, filp_head);
  676. intel_fb = to_intel_framebuffer(fb);
  677. /* if someone hotplugs something bigger than we have already
  678. * allocated, we are pwned. As really we can't resize an
  679. * fbdev that is in the wild currently due to fbdev not really
  680. * being designed for the lower layers moving stuff around
  681. * under it.
  682. * - so in the grand style of things - punt.
  683. */
  684. if ((fb->width < surface_width) ||
  685. (fb->height < surface_height)) {
  686. DRM_ERROR("fb not large enough for console\n");
  687. return -EINVAL;
  688. }
  689. }
  690. // fail
  691. info = intel_fb->base.fbdev;
  692. par = info->par;
  693. crtc_count = 0;
  694. /*
  695. * For each CRTC, set up the connector list for the CRTC's mode
  696. * set configuration.
  697. */
  698. list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  699. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  700. modeset = &intel_crtc->mode_set;
  701. modeset->fb = &intel_fb->base;
  702. conn_count = 0;
  703. list_for_each_entry(connector, &dev->mode_config.connector_list,
  704. head) {
  705. if (!connector->encoder)
  706. continue;
  707. if(connector->encoder->crtc == modeset->crtc) {
  708. modeset->connectors[conn_count++] = connector;
  709. if (conn_count > INTELFB_CONN_LIMIT)
  710. BUG();
  711. }
  712. }
  713. /* Zero out remaining connector pointers */
  714. for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
  715. modeset->connectors[i] = NULL;
  716. par->crtc_ids[crtc_count++] = crtc->base.id;
  717. modeset->num_connectors = conn_count;
  718. if (modeset->crtc->desired_mode) {
  719. if (modeset->mode)
  720. drm_mode_destroy(dev, modeset->mode);
  721. modeset->mode = drm_mode_duplicate(dev,
  722. modeset->crtc->desired_mode);
  723. }
  724. }
  725. par->crtc_count = crtc_count;
  726. if (new_fb) {
  727. info->var.pixclock = -1;
  728. if (register_framebuffer(info) < 0)
  729. return -EINVAL;
  730. } else
  731. intelfb_set_par(info);
  732. DRM_INFO("fb%d: %s frame buffer device\n", info->node,
  733. info->fix.id);
  734. /* Switch back to kernel console on panic */
  735. kernelfb_mode = *modeset;
  736. atomic_notifier_chain_register(&panic_notifier_list, &paniced);
  737. DRM_DEBUG("registered panic notifier\n");
  738. return 0;
  739. }
  740. /**
  741. * intelfb_restore - restore the framebuffer console (kernel) config
  742. *
  743. * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
  744. */
  745. void intelfb_restore(void)
  746. {
  747. int ret;
  748. if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) {
  749. DRM_ERROR("Failed to restore crtc configuration: %d\n",
  750. ret);
  751. }
  752. }
  753. static void intelfb_restore_work_fn(struct work_struct *ignored)
  754. {
  755. intelfb_restore();
  756. }
  757. static DECLARE_WORK(intelfb_restore_work, intelfb_restore_work_fn);
  758. static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
  759. {
  760. schedule_work(&intelfb_restore_work);
  761. }
  762. static struct sysrq_key_op sysrq_intelfb_restore_op = {
  763. .handler = intelfb_sysrq,
  764. .help_msg = "force-fb(V)",
  765. .action_msg = "Restore framebuffer console",
  766. };
  767. int intelfb_probe(struct drm_device *dev)
  768. {
  769. int ret;
  770. DRM_DEBUG("\n");
  771. /* something has changed in the lower levels of hell - deal with it
  772. here */
  773. /* two modes : a) 1 fb to rule all crtcs.
  774. b) one fb per crtc.
  775. two actions 1) new connected device
  776. 2) device removed.
  777. case a/1 : if the fb surface isn't big enough - resize the surface fb.
  778. if the fb size isn't big enough - resize fb into surface.
  779. if everything big enough configure the new crtc/etc.
  780. case a/2 : undo the configuration
  781. possibly resize down the fb to fit the new configuration.
  782. case b/1 : see if it is on a new crtc - setup a new fb and add it.
  783. case b/2 : teardown the new fb.
  784. */
  785. /* mode a first */
  786. /* search for an fb */
  787. if (i915_fbpercrtc == 1) {
  788. ret = intelfb_multi_fb_probe(dev);
  789. } else {
  790. ret = intelfb_single_fb_probe(dev);
  791. }
  792. register_sysrq_key('v', &sysrq_intelfb_restore_op);
  793. return ret;
  794. }
  795. EXPORT_SYMBOL(intelfb_probe);
  796. int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
  797. {
  798. struct fb_info *info;
  799. if (!fb)
  800. return -EINVAL;
  801. info = fb->fbdev;
  802. if (info) {
  803. unregister_framebuffer(info);
  804. iounmap(info->screen_base);
  805. framebuffer_release(info);
  806. }
  807. atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
  808. memset(&kernelfb_mode, 0, sizeof(struct drm_mode_set));
  809. return 0;
  810. }
  811. EXPORT_SYMBOL(intelfb_remove);
  812. MODULE_LICENSE("GPL and additional rights");