Guest User

Untitled

a guest
Jul 27th, 2018
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.81 KB | None | 0 0
  1. ---
  2. drivers/gpu/drm/Kconfig | 8 +
  3. drivers/gpu/drm/Makefile | 1 +
  4. drivers/gpu/drm/cirrus/Makefile | 6 +
  5. drivers/gpu/drm/cirrus/cirrus.h | 40 ++++
  6. drivers/gpu/drm/cirrus/cirrus_crtc.c | 277 +++++++++++++++++++++++++++
  7. drivers/gpu/drm/cirrus/cirrus_device.c | 111 +++++++++++
  8. drivers/gpu/drm/cirrus/cirrus_display.c | 70 +++++++
  9. drivers/gpu/drm/cirrus/cirrus_drv.c | 91 +++++++++
  10. drivers/gpu/drm/cirrus/cirrus_drv.h | 127 ++++++++++++
  11. drivers/gpu/drm/cirrus/cirrus_encoder.c | 139 ++++++++++++++
  12. drivers/gpu/drm/cirrus/cirrus_fbdev.c | 214 +++++++++++++++++++++
  13. drivers/gpu/drm/cirrus/cirrus_framebuffer.c | 48 +++++
  14. drivers/gpu/drm/cirrus/cirrus_kms.c | 59 ++++++
  15. drivers/gpu/drm/cirrus/cirrus_mode.h | 54 +++++
  16. drivers/gpu/drm/cirrus/cirrus_vga.c | 102 ++++++++++
  17. 15 files changed, 1347 insertions(+), 0 deletions(-)
  18. create mode 100644 drivers/gpu/drm/cirrus/Makefile
  19. create mode 100644 drivers/gpu/drm/cirrus/cirrus.h
  20. create mode 100644 drivers/gpu/drm/cirrus/cirrus_crtc.c
  21. create mode 100644 drivers/gpu/drm/cirrus/cirrus_device.c
  22. create mode 100644 drivers/gpu/drm/cirrus/cirrus_display.c
  23. create mode 100644 drivers/gpu/drm/cirrus/cirrus_drv.c
  24. create mode 100644 drivers/gpu/drm/cirrus/cirrus_drv.h
  25. create mode 100644 drivers/gpu/drm/cirrus/cirrus_encoder.c
  26. create mode 100644 drivers/gpu/drm/cirrus/cirrus_fbdev.c
  27. create mode 100644 drivers/gpu/drm/cirrus/cirrus_framebuffer.c
  28. create mode 100644 drivers/gpu/drm/cirrus/cirrus_kms.c
  29. create mode 100644 drivers/gpu/drm/cirrus/cirrus_mode.h
  30. create mode 100644 drivers/gpu/drm/cirrus/cirrus_vga.c
  31. diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
  32. index c58f691..2f54d2f 100644
  33. --- a/drivers/gpu/drm/Kconfig
  34. +++ b/drivers/gpu/drm/Kconfig
  35. @@ -126,6 +126,14 @@ config DRM_I915_KMS
  36. the driver to bind to PCI devices, which precludes loading things
  37. like intelfb.
  38.  
  39. +config DRM_KVM_CIRRUS
  40. + tristate "Kernel modesetting driver for qemu-kvm Cirrus emulation"
  41. + depends on DRM && PCI
  42. + select FB_CFB_FILLRECT
  43. + select FB_CFB_COPYAREA
  44. + select FB_CFB_IMAGEBLIT
  45. + select DRM_KMS_HELPER
  46. +
  47. config DRM_MGA
  48. tristate "Matrox g200/g400"
  49. depends on DRM && PCI
  50. diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
  51. index 89cf05a..11e486f 100644
  52. --- a/drivers/gpu/drm/Makefile
  53. +++ b/drivers/gpu/drm/Makefile
  54. @@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon/
  55. obj-$(CONFIG_DRM_MGA) += mga/
  56. obj-$(CONFIG_DRM_I810) += i810/
  57. obj-$(CONFIG_DRM_I915) += i915/
  58. +obj-$(CONFIG_DRM_KVM_CIRRUS) += cirrus/
  59. obj-$(CONFIG_DRM_SIS) += sis/
  60. obj-$(CONFIG_DRM_SAVAGE)+= savage/
  61. obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
  62. diff --git a/drivers/gpu/drm/cirrus/Makefile b/drivers/gpu/drm/cirrus/Makefile
  63. new file mode 100644
  64. index 0000000..126dd50
  65. --- /dev/null
  66. +++ b/drivers/gpu/drm/cirrus/Makefile
  67. @@ -0,0 +1,6 @@
  68. +ccflags-y := -Iinclude/drm
  69. +cirrus-y := cirrus_crtc.o cirrus_encoder.o cirrus_device.o cirrus_display.o \
  70. + cirrus_drv.o cirrus_fbdev.o cirrus_framebuffer.o \
  71. + cirrus_kms.o cirrus_vga.o
  72. +
  73. +obj-$(CONFIG_DRM_KVM_CIRRUS) += cirrus.o
  74. diff --git a/drivers/gpu/drm/cirrus/cirrus.h b/drivers/gpu/drm/cirrus/cirrus.h
  75. new file mode 100644
  76. index 0000000..44ad60a
  77. --- /dev/null
  78. +++ b/drivers/gpu/drm/cirrus/cirrus.h
  79. @@ -0,0 +1,40 @@
  80. +/*
  81. + * Copyright 2010 Matt Turner.
  82. + * Copyright 2011 Red Hat <mjg@redhat.com>
  83. + *
  84. + * This file is subject to the terms and conditions of the GNU General
  85. + * Public License version 2. See the file COPYING in the main
  86. + * directory of this archive for more details.
  87. + *
  88. + * Authors: Matthew Garrett
  89. + * Matt Turner
  90. + */
  91. +#ifndef __CIRRUS_H__
  92. +#define __CIRRUS_H__
  93. +
  94. +#include "cirrus_mode.h"
  95. +
  96. +struct cirrus_mc {
  97. + resource_size_t vram_size;
  98. + resource_size_t vram_base;
  99. +};
  100. +
  101. +struct cirrus_device {
  102. + struct device *dev;
  103. + struct drm_device *ddev;
  104. + struct pci_dev *pdev;
  105. + unsigned long flags;
  106. +
  107. + resource_size_t rmmio_base;
  108. + resource_size_t rmmio_size;
  109. + void __iomem *rmmio;
  110. +
  111. + drm_local_map_t *framebuffer;
  112. +
  113. + struct cirrus_mc mc;
  114. + struct cirrus_mode_info mode_info;
  115. +
  116. + int num_crtc;
  117. +};
  118. +
  119. +#endif /* __CIRRUS_H__ */
  120. diff --git a/drivers/gpu/drm/cirrus/cirrus_crtc.c b/drivers/gpu/drm/cirrus/cirrus_crtc.c
  121. new file mode 100644
  122. index 0000000..afce8f2
  123. --- /dev/null
  124. +++ b/drivers/gpu/drm/cirrus/cirrus_crtc.c
  125. @@ -0,0 +1,277 @@
  126. +/*
  127. + * Copyright 2000,2001 Sven Luther.
  128. + * Copyright 2010 Matt Turner.
  129. + * Copyright 2011 Red Hat <mjg@redhat.com>
  130. + *
  131. + * This file is subject to the terms and conditions of the GNU General
  132. + * Public License version 2. See the file COPYING in the main
  133. + * directory of this archive for more details.
  134. + *
  135. + * Authors: Matthew Garrett
  136. + * Matt Turner
  137. + * Sven Luther
  138. + * Thomas Witzel
  139. + * Alan Hourihane
  140. + *
  141. + * Portions of this code derived from cirrusfb.c:
  142. + * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
  143. + *
  144. + * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
  145. + */
  146. +#include "drmP.h"
  147. +#include "drm.h"
  148. +#include "drm_crtc_helper.h"
  149. +
  150. +#include <video/cirrus.h>
  151. +
  152. +#include "cirrus.h"
  153. +#include "cirrus_drv.h"
  154. +#include "cirrus_mode.h"
  155. +
  156. +#define CIRRUS_LUT_SIZE 256
  157. +
  158. +#define PALETTE_INDEX 0x8
  159. +#define PALETTE_DATA 0x9
  160. +
  161. +/*
  162. + * This file contains setup code for the CRTC.
  163. + */
  164. +
  165. +static void cirrus_crtc_load_lut(struct drm_crtc *crtc)
  166. +{
  167. + struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
  168. + struct drm_device *dev = crtc->dev;
  169. + struct cirrus_device *cdev = dev->dev_private;
  170. + int i;
  171. +
  172. + if (!crtc->enabled)
  173. + return;
  174. +
  175. + for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
  176. + /* VGA registers */
  177. + WREG8(PALETTE_INDEX, i);
  178. + WREG8(PALETTE_DATA, cirrus_crtc->lut_r[i]);
  179. + WREG8(PALETTE_DATA, cirrus_crtc->lut_g[i]);
  180. + WREG8(PALETTE_DATA, cirrus_crtc->lut_b[i]);
  181. + }
  182. +}
  183. +
  184. +/*
  185. + * The DRM core requires DPMS functions, but they make little sense in our
  186. + * case and so are just stubs
  187. + */
  188. +
  189. +static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
  190. +{
  191. +}
  192. +
  193. +/*
  194. + * The core passes the desired mode to the CRTC code to see whether any
  195. + * CRTC-specific modifications need to be made to it. We're in a position
  196. + * to just pass that straight through, so this does nothing
  197. + */
  198. +static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
  199. + struct drm_display_mode *mode,
  200. + struct drm_display_mode *adjusted_mode)
  201. +{
  202. + return true;
  203. +}
  204. +
  205. +/*
  206. + * The meat of this driver. The core passes us a mode and we have to program
  207. + * it. The modesetting here is the bare minimum required to satisfy the qemu
  208. + * emulation of this hardware, and running this against a real device is
  209. + * likely to result in an inadequately programmed mode. We've already had
  210. + * the opportunity to modify the mode, so whatever we receive here should
  211. + * be something that can be correctly programmed and displayed
  212. + */
  213. +static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
  214. + struct drm_display_mode *mode,
  215. + struct drm_display_mode *adjusted_mode,
  216. + int x, int y, struct drm_framebuffer *old_fb)
  217. +{
  218. + struct drm_device *dev = crtc->dev;
  219. + struct cirrus_device *cdev = dev->dev_private;
  220. + int hsyncstart, hsyncend, htotal, hdispend;
  221. + int vtotal, vdispend;
  222. + int tmp;
  223. +
  224. + htotal = mode->htotal / 8;
  225. + hsyncend = mode->hsync_end / 8;
  226. + hsyncstart = mode->hsync_start / 8;
  227. + hdispend = mode->hdisplay / 8;
  228. +
  229. + vtotal = mode->vtotal;
  230. + vdispend = mode->vdisplay;
  231. +
  232. + vdispend -= 1;
  233. + vtotal -= 2;
  234. +
  235. + htotal -= 5;
  236. + hdispend -= 1;
  237. + hsyncstart += 1;
  238. + hsyncend += 1;
  239. +
  240. + WREG_CRT(VGA_CRTC_V_SYNC_END, 0x20);
  241. + WREG_CRT(VGA_CRTC_H_TOTAL, htotal);
  242. + WREG_CRT(VGA_CRTC_H_DISP, hdispend);
  243. + WREG_CRT(VGA_CRTC_H_SYNC_START, hsyncstart);
  244. + WREG_CRT(VGA_CRTC_H_SYNC_END, hsyncend);
  245. + WREG_CRT(VGA_CRTC_V_TOTAL, vtotal & 0xff);
  246. + WREG_CRT(VGA_CRTC_V_DISP_END, vdispend & 0xff);
  247. +
  248. + tmp = 0x40;
  249. + if ((vdispend + 1) & 512)
  250. + tmp |= 0x20;
  251. + WREG_CRT(VGA_CRTC_MAX_SCAN, tmp);
  252. +
  253. + /*
  254. + * Overflow bits for values that don't fit in the standard registers
  255. + */
  256. + tmp = 16;
  257. + if (vtotal & 256)
  258. + tmp |= 1;
  259. + if (vdispend & 256)
  260. + tmp |= 2;
  261. + if ((vdispend + 1) & 256)
  262. + tmp |= 8;
  263. + if (vtotal & 512)
  264. + tmp |= 32;
  265. + if (vdispend & 512)
  266. + tmp |= 64;
  267. + WREG_CRT(VGA_CRTC_OVERFLOW, tmp);
  268. +
  269. + tmp = 0;
  270. +
  271. + /* More overflow bits */
  272. +
  273. + if ((htotal + 5) & 64)
  274. + tmp |= 16;
  275. + if ((htotal + 5) & 128)
  276. + tmp |= 32;
  277. + if (vtotal & 256)
  278. + tmp |= 64;
  279. + if (vtotal & 512)
  280. + tmp |= 128;
  281. +
  282. + WREG_CRT(CL_CRT1A, tmp);
  283. +
  284. + /* Disable Hercules/CGA compatibility */
  285. + WREG_CRT(VGA_CRTC_MODE, 0x03);
  286. +
  287. + return 0;
  288. +}
  289. +
  290. +/*
  291. + * This is called before a mode is programmed. A typical use might be to
  292. + * enable DPMS during the programming to avoid seeing intermediate stages,
  293. + * but that's not relevant to us
  294. + */
  295. +static void cirrus_crtc_prepare(struct drm_crtc *crtc)
  296. +{
  297. +}
  298. +
  299. +/*
  300. + * This is called after a mode is programmed. It should reverse anything done
  301. + * by the prepare function
  302. + */
  303. +static void cirrus_crtc_commit(struct drm_crtc *crtc)
  304. +{
  305. +}
  306. +
  307. +/*
  308. + * The core can pass us a set of gamma values to program. We actually only
  309. + * use this for 8-bit mode so can't perform smooth fades on deeper modes,
  310. + * but it's a requirement that we provide the function
  311. + */
  312. +static void cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
  313. + u16 *blue, uint32_t start, uint32_t size)
  314. +{
  315. + struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
  316. + int i;
  317. +
  318. + if (size != CIRRUS_LUT_SIZE)
  319. + return;
  320. +
  321. + for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
  322. + cirrus_crtc->lut_r[i] = red[i];
  323. + cirrus_crtc->lut_g[i] = green[i];
  324. + cirrus_crtc->lut_b[i] = blue[i];
  325. + }
  326. + cirrus_crtc_load_lut(crtc);
  327. +}
  328. +
  329. +/* Simple cleanup function */
  330. +static void cirrus_crtc_destroy(struct drm_crtc *crtc)
  331. +{
  332. + struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
  333. +
  334. + drm_crtc_cleanup(crtc);
  335. + kfree(cirrus_crtc);
  336. +}
  337. +
  338. +/* These provide the minimum set of functions required to handle a CRTC */
  339. +static const struct drm_crtc_funcs cirrus_crtc_funcs = {
  340. + .gamma_set = cirrus_crtc_gamma_set,
  341. + .set_config = drm_crtc_helper_set_config,
  342. + .destroy = cirrus_crtc_destroy,
  343. +};
  344. +
  345. +static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
  346. + .dpms = cirrus_crtc_dpms,
  347. + .mode_fixup = cirrus_crtc_mode_fixup,
  348. + .mode_set = cirrus_crtc_mode_set,
  349. + .prepare = cirrus_crtc_prepare,
  350. + .commit = cirrus_crtc_commit,
  351. + .load_lut = cirrus_crtc_load_lut,
  352. +};
  353. +
  354. +/* CRTC setup */
  355. +void cirrus_crtc_init(struct drm_device *dev)
  356. +{
  357. + struct cirrus_device *cdev = dev->dev_private;
  358. + struct cirrus_crtc *cirrus_crtc;
  359. + int i;
  360. +
  361. + cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
  362. + (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
  363. + GFP_KERNEL);
  364. +
  365. + if (cirrus_crtc == NULL)
  366. + return;
  367. +
  368. + drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
  369. +
  370. + drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
  371. + cdev->mode_info.crtc = cirrus_crtc;
  372. +
  373. + for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
  374. + cirrus_crtc->lut_r[i] = i;
  375. + cirrus_crtc->lut_g[i] = i;
  376. + cirrus_crtc->lut_b[i] = i;
  377. + }
  378. +
  379. + drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
  380. +}
  381. +
  382. +/** Sets the color ramps on behalf of fbcon */
  383. +void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
  384. + u16 blue, int regno)
  385. +{
  386. + struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
  387. +
  388. + cirrus_crtc->lut_r[regno] = red;
  389. + cirrus_crtc->lut_g[regno] = green;
  390. + cirrus_crtc->lut_b[regno] = blue;
  391. +}
  392. +
  393. +/** Gets the color ramps on behalf of fbcon */
  394. +void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
  395. + u16 *blue, int regno)
  396. +{
  397. + struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
  398. +
  399. + *red = cirrus_crtc->lut_r[regno];
  400. + *green = cirrus_crtc->lut_g[regno];
  401. + *blue = cirrus_crtc->lut_b[regno];
  402. +}
  403. diff --git a/drivers/gpu/drm/cirrus/cirrus_device.c b/drivers/gpu/drm/cirrus/cirrus_device.c
  404. new file mode 100644
  405. index 0000000..685c53b
  406. --- /dev/null
  407. +++ b/drivers/gpu/drm/cirrus/cirrus_device.c
  408. @@ -0,0 +1,111 @@
  409. +/*
  410. + * Copyright 2010 Matt Turner.
  411. + * Copyright 2011 Red Hat <mjg@redhat.com>
  412. + *
  413. + * This file is subject to the terms and conditions of the GNU General
  414. + * Public License version 2. See the file COPYING in the main
  415. + * directory of this archive for more details.
  416. + *
  417. + * Authors: Matthew Garrett
  418. + * Matt Turner
  419. + */
  420. +#include "drmP.h"
  421. +#include "drm.h"
  422. +
  423. +#include "cirrus.h"
  424. +#include "cirrus_drv.h"
  425. +
  426. +/* Unmap the framebuffer from the core and release the memory */
  427. +static void cirrus_vram_fini(struct cirrus_device *cdev)
  428. +{
  429. + iounmap(cdev->rmmio);
  430. + cdev->rmmio = NULL;
  431. + if (cdev->framebuffer)
  432. + drm_rmmap(cdev->ddev, cdev->framebuffer);
  433. + if (cdev->mc.vram_base)
  434. + release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
  435. +}
  436. +
  437. +/* Map the framebuffer from the card and configure the core */
  438. +static int cirrus_vram_init(struct cirrus_device *cdev)
  439. +{
  440. + int ret;
  441. +
  442. + /* BAR 0 is VRAM */
  443. + cdev->mc.vram_base = pci_resource_start(cdev->ddev->pdev, 0);
  444. + /* We have 4MB of VRAM */
  445. + cdev->mc.vram_size = 4 * 1024 * 1024;
  446. +
  447. + if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
  448. + "cirrusdrmfb_vram")) {
  449. + CIRRUS_ERROR("can't reserve VRAM\n");
  450. + return -ENXIO;
  451. + }
  452. +
  453. + /*
  454. + * Tell the kernel that vram is available to userspace. This driver
  455. + * provides no acceleration and doesn't support any off-screen buffers
  456. + * so we can just map the entirity of vram as a framebuffer.
  457. + */
  458. + ret = drm_addmap(cdev->ddev, cdev->mc.vram_base, cdev->mc.vram_size,
  459. + _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
  460. + &cdev->framebuffer);
  461. +
  462. + if (ret) {
  463. + cirrus_vram_fini(cdev);
  464. + return ret;
  465. + }
  466. +
  467. + return 0;
  468. +}
  469. +
  470. +/*
  471. + * Our emulated hardware has two sets of memory. One is video RAM and can
  472. + * simply be used as a linear framebuffer - the other provides mmio access
  473. + * to the display registers. The latter can also be accessed via IO port
  474. + * access, but we map the range and use mmio to program them instead
  475. + */
  476. +
  477. +int cirrus_device_init(struct cirrus_device *cdev,
  478. + struct drm_device *ddev,
  479. + struct pci_dev *pdev, uint32_t flags)
  480. +{
  481. + int ret;
  482. +
  483. + cdev->dev = &pdev->dev;
  484. + cdev->ddev = ddev;
  485. + cdev->pdev = pdev;
  486. + cdev->flags = flags;
  487. +
  488. + /* Hardcode the number of CRTCs to 1 */
  489. + cdev->num_crtc = 1;
  490. +
  491. + /* BAR 0 is the framebuffer, BAR 1 contains registers */
  492. + cdev->rmmio_base = pci_resource_start(cdev->ddev->pdev, 1);
  493. + cdev->rmmio_size = pci_resource_len(cdev->ddev->pdev, 1);
  494. +
  495. + if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
  496. + "cirrusdrmfb_mmio")) {
  497. + CIRRUS_ERROR("can't reserve mmio registers\n");
  498. + return -ENOMEM;
  499. + }
  500. +
  501. + cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
  502. +
  503. + if (cdev->rmmio == NULL)
  504. + return -ENOMEM;
  505. +
  506. + ret = cirrus_vram_init(cdev);
  507. + if (ret) {
  508. + release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
  509. + return ret;
  510. + }
  511. +
  512. + return 0;
  513. +}
  514. +
  515. +void cirrus_device_fini(struct cirrus_device *cdev)
  516. +{
  517. + release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
  518. + cirrus_vram_fini(cdev);
  519. +}
  520. diff --git a/drivers/gpu/drm/cirrus/cirrus_display.c b/drivers/gpu/drm/cirrus/cirrus_display.c
  521. new file mode 100644
  522. index 0000000..77f4dcf
  523. --- /dev/null
  524. +++ b/drivers/gpu/drm/cirrus/cirrus_display.c
  525. @@ -0,0 +1,70 @@
  526. +/*
  527. + * Copyright 2010 Matt Turner.
  528. + * Copyright 2011 Red Hat <mjg@redhat.com>
  529. + *
  530. + * This file is subject to the terms and conditions of the GNU General
  531. + * Public License version 2. See the file COPYING in the main
  532. + * directory of this archive for more details.
  533. + *
  534. + * Authors: Matthew Garrett
  535. + * Matt Turner
  536. + */
  537. +#include "drmP.h"
  538. +#include "drm.h"
  539. +#include "drm_crtc_helper.h"
  540. +
  541. +#include "cirrus.h"
  542. +#include "cirrus_drv.h"
  543. +
  544. +/*
  545. + * This file contains simple functions for initialising the driver
  546. + */
  547. +
  548. +int cirrus_modeset_init(struct cirrus_device *cdev)
  549. +{
  550. + struct drm_encoder *encoder;
  551. + struct drm_connector *connector;
  552. + int ret;
  553. +
  554. + drm_mode_config_init(cdev->ddev);
  555. + cdev->mode_info.mode_config_initialized = true;
  556. +
  557. + cdev->ddev->mode_config.max_width = CIRRUS_MAX_FB_WIDTH;
  558. + cdev->ddev->mode_config.max_height = CIRRUS_MAX_FB_HEIGHT;
  559. +
  560. + cdev->ddev->mode_config.fb_base = cdev->mc.vram_base;
  561. +
  562. + cirrus_crtc_init(cdev->ddev);
  563. +
  564. + encoder = cirrus_encoder_init(cdev->ddev);
  565. + if (!encoder) {
  566. + CIRRUS_ERROR("cirrus_encoder_init failed\n");
  567. + return -1;
  568. + }
  569. +
  570. + connector = cirrus_vga_init(cdev->ddev);
  571. + if (!connector) {
  572. + CIRRUS_ERROR("cirrus_vga_init failed\n");
  573. + return -1;
  574. + }
  575. +
  576. + drm_mode_connector_attach_encoder(connector, encoder);
  577. +
  578. + ret = cirrus_fbdev_init(cdev);
  579. + if (ret) {
  580. + CIRRUS_ERROR("cirrus_fbdev_init failed\n");
  581. + return ret;
  582. + }
  583. +
  584. + return 0;
  585. +}
  586. +
  587. +void cirrus_modeset_fini(struct cirrus_device *cdev)
  588. +{
  589. + cirrus_fbdev_fini(cdev);
  590. +
  591. + if (cdev->mode_info.mode_config_initialized) {
  592. + drm_mode_config_cleanup(cdev->ddev);
  593. + cdev->mode_info.mode_config_initialized = false;
  594. + }
  595. +}
  596. diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
  597. new file mode 100644
  598. index 0000000..ecc8e8d
  599. --- /dev/null
  600. +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
  601. @@ -0,0 +1,91 @@
  602. +/*
  603. + * Copyright 2010 Matt Turner.
  604. + * Copyright 2011 Red Hat <mjg@redhat.com>
  605. + *
  606. + * This file is subject to the terms and conditions of the GNU General
  607. + * Public License version 2. See the file COPYING in the main
  608. + * directory of this archive for more details.
  609. + *
  610. + * Authors: Matthew Garrett
  611. + * Matt Turner
  612. + */
  613. +#include "drmP.h"
  614. +#include "drm.h"
  615. +
  616. +#include "cirrus_drv.h"
  617. +
  618. +#include "drm_pciids.h"
  619. +
  620. +/*
  621. + * This is the generic driver code. This binds the driver to the drm core,
  622. + * which then performs further device association and calls our graphics init
  623. + * functions
  624. + */
  625. +
  626. +static struct drm_driver driver;
  627. +
  628. +static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
  629. + { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
  630. + 0, 0 },
  631. + {0,}
  632. +};
  633. +
  634. +static int __devinit
  635. +cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  636. +{
  637. + return drm_get_pci_dev(pdev, ent, &driver);
  638. +}
  639. +
  640. +static void cirrus_pci_remove(struct pci_dev *pdev)
  641. +{
  642. + struct drm_device *dev = pci_get_drvdata(pdev);
  643. +
  644. + drm_put_dev(dev);
  645. +}
  646. +
  647. +static struct drm_driver driver = {
  648. + .driver_features = DRIVER_MODESET,
  649. + .load = cirrus_driver_load,
  650. + .unload = cirrus_driver_unload,
  651. + .reclaim_buffers = drm_core_reclaim_buffers,
  652. + .fops = {
  653. + .owner = THIS_MODULE,
  654. + .open = drm_open,
  655. + .release = drm_release,
  656. + .unlocked_ioctl = drm_ioctl,
  657. + .mmap = drm_mmap,
  658. + .poll = drm_poll,
  659. + .fasync = drm_fasync,
  660. + },
  661. + .name = DRIVER_NAME,
  662. + .desc = DRIVER_DESC,
  663. + .date = DRIVER_DATE,
  664. + .major = DRIVER_MAJOR,
  665. + .minor = DRIVER_MINOR,
  666. + .patchlevel = DRIVER_PATCHLEVEL,
  667. +};
  668. +
  669. +static struct pci_driver cirrus_pci_driver = {
  670. + .name = DRIVER_NAME,
  671. + .id_table = pciidlist,
  672. + .probe = cirrus_pci_probe,
  673. + .remove = cirrus_pci_remove,
  674. +};
  675. +
  676. +static int __init cirrus_init(void)
  677. +{
  678. + return drm_pci_init(&driver, &cirrus_pci_driver);
  679. +}
  680. +
  681. +static void __exit cirrus_exit(void)
  682. +{
  683. + drm_pci_exit(&driver, &cirrus_pci_driver);
  684. +}
  685. +
  686. +module_init(cirrus_init);
  687. +module_exit(cirrus_exit);
  688. +
  689. +MODULE_DEVICE_TABLE(pci, pciidlist);
  690. +MODULE_AUTHOR(DRIVER_AUTHOR);
  691. +MODULE_DESCRIPTION(DRIVER_DESC);
  692. +MODULE_LICENSE("GPL");
  693. diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
  694. new file mode 100644
  695. index 0000000..7a93f3e
  696. --- /dev/null
  697. +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
  698. @@ -0,0 +1,127 @@
  699. +/*
  700. + * Copyright 2010 Matt Turner.
  701. + * Copyright 2011 Red Hat <mjg@redhat.com>
  702. + *
  703. + * This file is subject to the terms and conditions of the GNU General
  704. + * Public License version 2. See the file COPYING in the main
  705. + * directory of this archive for more details.
  706. + *
  707. + * Authors: Matthew Garrett
  708. + * Matt Turner
  709. + */
  710. +#ifndef __CIRRUS_DRV_H__
  711. +#define __CIRRUS_DRV_H__
  712. +
  713. +#include <video/vga.h>
  714. +
  715. +#define DRIVER_AUTHOR "Matthew Garrett"
  716. +
  717. +#define DRIVER_NAME "cirrus"
  718. +#define DRIVER_DESC "qemu Cirrus emulation"
  719. +#define DRIVER_DATE "20110418"
  720. +
  721. +#define DRIVER_MAJOR 1
  722. +#define DRIVER_MINOR 0
  723. +#define DRIVER_PATCHLEVEL 0
  724. +
  725. +#define CIRRUS_INFO(fmt, arg...) DRM_INFO(DRIVER_NAME ": " fmt, ##arg)
  726. +#define CIRRUS_ERROR(fmt, arg...) DRM_ERROR(DRIVER_NAME ": " fmt, ##arg)
  727. +
  728. +#define CIRRUSFB_CONN_LIMIT 4
  729. +
  730. +#define RREG8(reg) ioread8(((void __iomem *)cdev->rmmio) + (reg))
  731. +#define WREG8(reg, v) iowrite8(v, ((void __iomem *)cdev->rmmio) + (reg))
  732. +#define RREG32(reg) ioread32(((void __iomem *)cdev->rmmio) + (reg))
  733. +#define WREG32(reg, v) iowrite32(v, ((void __iomem *)cdev->rmmio) + (reg))
  734. +
  735. +#define SEQ_INDEX 4
  736. +#define SEQ_DATA 5
  737. +
  738. +#define WREG_SEQ(reg, v) \
  739. + do { \
  740. + WREG8(SEQ_INDEX, reg); \
  741. + WREG8(SEQ_DATA, v); \
  742. + } while (0) \
  743. +
  744. +#define CRT_INDEX 0x14
  745. +#define CRT_DATA 0x15
  746. +
  747. +#define WREG_CRT(reg, v) \
  748. + do { \
  749. + WREG8(CRT_INDEX, reg); \
  750. + WREG8(CRT_DATA, v); \
  751. + } while (0) \
  752. +
  753. +#define GFX_INDEX 0xe
  754. +#define GFX_DATA 0xf
  755. +
  756. +#define WREG_GFX(reg, v) \
  757. + do { \
  758. + WREG8(GFX_INDEX, reg); \
  759. + WREG8(GFX_DATA, v); \
  760. + } while (0) \
  761. +
  762. +/*
  763. + * Cirrus has a "hidden" DAC register that can be accessed by writing to
  764. + * the pixel mask register to reset the state, then reading from the register
  765. + * four times. The next write will then pass to the DAC
  766. + */
  767. +#define WREG_HDR(v) \
  768. + do { \
  769. + WREG8(0x6, 0xff); \
  770. + RREG8(0x6); \
  771. + RREG8(0x6); \
  772. + RREG8(0x6); \
  773. + RREG8(0x6); \
  774. + WREG8(0x6, v); \
  775. + } while (0) \
  776. +
  777. +
  778. +#include "cirrus.h"
  779. +
  780. + /* cirrus_crtc.c */
  781. +void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
  782. + u16 blue, int regno);
  783. +void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
  784. + u16 *blue, int regno);
  785. +void cirrus_crtc_init(struct drm_device *dev);
  786. +
  787. + /* cirrus_encoder.c */
  788. +struct drm_encoder *cirrus_encoder_init(struct drm_device *dev);
  789. +
  790. + /* cirrus_device.c */
  791. +int cirrus_device_init(struct cirrus_device *cdev,
  792. + struct drm_device *ddev,
  793. + struct pci_dev *pdev,
  794. + uint32_t flags);
  795. +void cirrus_device_fini(struct cirrus_device *cdev);
  796. +
  797. + /* cirrus_display.c */
  798. +int cirrus_modeset_init(struct cirrus_device *cdev);
  799. +void cirrus_modeset_fini(struct cirrus_device *cdev);
  800. +
  801. + /* cirrus_fbdev.c */
  802. +int cirrus_fbdev_init(struct cirrus_device *cdev);
  803. +void cirrus_fbdev_fini(struct cirrus_device *cdev);
  804. +
  805. + /* cirrus_framebuffer.c */
  806. +int cirrus_framebuffer_init(struct drm_device *dev,
  807. + struct cirrus_framebuffer *gfb,
  808. + struct drm_mode_fb_cmd *mode_cmd);
  809. +
  810. + /* cirrus_irq.c */
  811. +void cirrus_driver_irq_preinstall(struct drm_device *dev);
  812. +int cirrus_driver_irq_postinstall(struct drm_device *dev);
  813. +void cirrus_driver_irq_uninstall(struct drm_device *dev);
  814. +irqreturn_t cirrus_driver_irq_handler(DRM_IRQ_ARGS);
  815. +
  816. + /* cirrus_kms.c */
  817. +int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
  818. +int cirrus_driver_unload(struct drm_device *dev);
  819. +extern struct drm_ioctl_desc cirrus_ioctls[];
  820. +extern int cirrus_max_ioctl;
  821. +
  822. + /* cirrus_vga.c */
  823. +struct drm_connector *cirrus_vga_init(struct drm_device *dev);
  824. +
  825. +#endif /* __CIRRUS_DRV_H__ */
  826. diff --git a/drivers/gpu/drm/cirrus/cirrus_encoder.c b/drivers/gpu/drm/cirrus/cirrus_encoder.c
  827. new file mode 100644
  828. index 0000000..3556ead
  829. --- /dev/null
  830. +++ b/drivers/gpu/drm/cirrus/cirrus_encoder.c
  831. @@ -0,0 +1,139 @@
  832. +/*
  833. + * Copyright 2010 Matt Turner.
  834. + * Copyright 2011 Red Hat <mjg@redhat.com>
  835. + *
  836. + * This file is subject to the terms and conditions of the GNU General
  837. + * Public License version 2. See the file COPYING in the main
  838. + * directory of this archive for more details.
  839. + *
  840. + * Authors: Matthew Garrett
  841. + * Matt Turner
  842. + */
  843. +#include "drmP.h"
  844. +#include "drm.h"
  845. +#include "drm_crtc_helper.h"
  846. +
  847. +#include <video/cirrus.h>
  848. +
  849. +#include "cirrus.h"
  850. +#include "cirrus_drv.h"
  851. +#include "cirrus_mode.h"
  852. +
  853. +/*
  854. + * The encoder comes after the CRTC in the output pipeline, but before
  855. + * the connector. It's responsible for ensuring that the digital
  856. + * stream is appropriately converted into the output format. Setup is
  857. + * very simple in this case - all we have to do is inform qemu of the
  858. + * colour depth in order to ensure that it displays appropriately
  859. + */
  860. +
  861. +/*
  862. + * These functions are analagous to those in the CRTC code, but are intended
  863. + * to handle any encoder-specific limitations
  864. + */
  865. +static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder,
  866. + struct drm_display_mode *mode,
  867. + struct drm_display_mode *adjusted_mode)
  868. +{
  869. + return true;
  870. +}
  871. +
  872. +static void cirrus_encoder_mode_set(struct drm_encoder *encoder,
  873. + struct drm_display_mode *mode,
  874. + struct drm_display_mode *adjusted_mode)
  875. +{
  876. + struct drm_device *dev = encoder->dev;
  877. + struct cirrus_device *cdev = dev->dev_private;
  878. +
  879. + unsigned char tmp;
  880. +
  881. + switch (encoder->crtc->fb->bits_per_pixel) {
  882. + case 8:
  883. + tmp = 0x0;
  884. + break;
  885. + case 16:
  886. + /* Enable 16 bit mode */
  887. + WREG_HDR(0x01);
  888. + tmp = 0x6;
  889. + break;
  890. + case 24:
  891. + tmp = 0x4;
  892. + break;
  893. + case 32:
  894. + tmp = 0x8;
  895. + break;
  896. + default:
  897. + return;
  898. + }
  899. +
  900. + /* Enable packed pixel graphics modes */
  901. + tmp |= 0x1;
  902. + WREG_SEQ(0x7, tmp);
  903. +
  904. + /* Program the pitch */
  905. + tmp = encoder->crtc->fb->pitch / 8;
  906. + WREG_CRT(VGA_CRTC_OFFSET, tmp);
  907. +
  908. + /* Enable extended blanking and pitch bits, and enable full memory */
  909. + tmp = 0x22;
  910. + if (encoder->crtc->fb->pitch >= 2048)
  911. + tmp |= 0x10;
  912. + WREG_CRT(0x1b, tmp);
  913. +
  914. + /* Enable high-colour modes */
  915. + WREG_GFX(VGA_GFX_MODE, 0x40);
  916. +
  917. + /* And set graphics mode */
  918. + WREG_GFX(VGA_GFX_MISC, 0x01);
  919. +}
  920. +
  921. +static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state)
  922. +{
  923. + return;
  924. +}
  925. +
  926. +static void cirrus_encoder_prepare(struct drm_encoder *encoder)
  927. +{
  928. +}
  929. +
  930. +static void cirrus_encoder_commit(struct drm_encoder *encoder)
  931. +{
  932. +}
  933. +
  934. +void cirrus_encoder_destroy(struct drm_encoder *encoder)
  935. +{
  936. + struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
  937. + drm_encoder_cleanup(encoder);
  938. + kfree(cirrus_encoder);
  939. +}
  940. +
  941. +static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = {
  942. + .dpms = cirrus_encoder_dpms,
  943. + .mode_fixup = cirrus_encoder_mode_fixup,
  944. + .mode_set = cirrus_encoder_mode_set,
  945. + .prepare = cirrus_encoder_prepare,
  946. + .commit = cirrus_encoder_commit,
  947. +};
  948. +
  949. +static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs = {
  950. + .destroy = cirrus_encoder_destroy,
  951. +};
  952. +
  953. +struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
  954. +{
  955. + struct drm_encoder *encoder;
  956. + struct cirrus_encoder *cirrus_encoder;
  957. +
  958. + cirrus_encoder = kzalloc(sizeof(struct cirrus_encoder), GFP_KERNEL);
  959. + if (!cirrus_encoder)
  960. + return NULL;
  961. +
  962. + encoder = &cirrus_encoder->base;
  963. + encoder->possible_crtcs = 0x1;
  964. +
  965. + drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
  966. + DRM_MODE_ENCODER_DAC);
  967. + drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
  968. +
  969. + return encoder;
  970. +}
  971. diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
  972. new file mode 100644
  973. index 0000000..086e647
  974. --- /dev/null
  975. +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
  976. @@ -0,0 +1,214 @@
  977. +/*
  978. + * Copyright 2010 Matt Turner.
  979. + * Copyright 2011 Red Hat <mjg@redhat.com>
  980. + *
  981. + * This file is subject to the terms and conditions of the GNU General
  982. + * Public License version 2. See the file COPYING in the main
  983. + * directory of this archive for more details.
  984. + *
  985. + * Authors: Matthew Garrett
  986. + * Matt Turner
  987. + */
  988. +#include "drmP.h"
  989. +#include "drm.h"
  990. +#include "drm_fb_helper.h"
  991. +
  992. +#include <linux/fb.h>
  993. +
  994. +#include "cirrus.h"
  995. +#include "cirrus_drv.h"
  996. +
  997. +struct cirrus_fbdev {
  998. + struct drm_fb_helper helper;
  999. + struct cirrus_framebuffer gfb;
  1000. + struct list_head fbdev_list;
  1001. + struct cirrus_device *cdev;
  1002. +};
  1003. +
  1004. +static struct fb_ops cirrusfb_ops = {
  1005. + .owner = THIS_MODULE,
  1006. + .fb_check_var = drm_fb_helper_check_var,
  1007. + .fb_set_par = drm_fb_helper_set_par,
  1008. + .fb_fillrect = cfb_fillrect,
  1009. + .fb_copyarea = cfb_copyarea,
  1010. + .fb_imageblit = cfb_imageblit,
  1011. + .fb_pan_display = drm_fb_helper_pan_display,
  1012. + .fb_blank = drm_fb_helper_blank,
  1013. + .fb_setcmap = drm_fb_helper_setcmap,
  1014. +};
  1015. +
  1016. +static int cirrusfb_create(struct cirrus_fbdev *gfbdev,
  1017. + struct drm_fb_helper_surface_size *sizes)
  1018. +{
  1019. + struct cirrus_device *cdev = gfbdev->cdev;
  1020. + struct fb_info *info;
  1021. + struct drm_framebuffer *fb;
  1022. + struct drm_map_list *r_list, *list_t;
  1023. + struct drm_local_map *map = NULL;
  1024. + struct drm_mode_fb_cmd mode_cmd;
  1025. + struct device *device = &cdev->pdev->dev;
  1026. + int ret;
  1027. +
  1028. + mode_cmd.width = sizes->surface_width;
  1029. + mode_cmd.height = sizes->surface_height;
  1030. + mode_cmd.bpp = sizes->surface_bpp;
  1031. + mode_cmd.depth = sizes->surface_depth;
  1032. + mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 7) / 8);
  1033. +
  1034. + info = framebuffer_alloc(0, device);
  1035. + if (info == NULL)
  1036. + return -ENOMEM;
  1037. +
  1038. + info->par = gfbdev;
  1039. +
  1040. + ret = cirrus_framebuffer_init(cdev->ddev, &gfbdev->gfb, &mode_cmd);
  1041. + if (ret)
  1042. + return ret;
  1043. +
  1044. + fb = &gfbdev->gfb.base;
  1045. + if (!fb) {
  1046. + CIRRUS_INFO("fb is NULL\n");
  1047. + return -EINVAL;
  1048. + }
  1049. +
  1050. + /* setup helper */
  1051. + gfbdev->helper.fb = fb;
  1052. + gfbdev->helper.fbdev = info;
  1053. +
  1054. + strcpy(info->fix.id, "cirrusdrmfb");
  1055. +
  1056. + drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
  1057. +
  1058. + info->flags = FBINFO_DEFAULT;
  1059. + info->fbops = &cirrusfb_ops;
  1060. +
  1061. + drm_fb_helper_fill_var(info, &gfbdev->helper, sizes->fb_width,
  1062. + sizes->fb_height);
  1063. +
  1064. + /* setup aperture base/size for vesafb takeover */
  1065. + info->apertures = alloc_apertures(1);
  1066. + if (!info->apertures) {
  1067. + ret = -ENOMEM;
  1068. + goto out_iounmap;
  1069. + }
  1070. + info->apertures->ranges[0].base = cdev->ddev->mode_config.fb_base;
  1071. + info->apertures->ranges[0].size = cdev->mc.vram_size;
  1072. +
  1073. + list_for_each_entry_safe(r_list, list_t, &cdev->ddev->maplist, head) {
  1074. + map = r_list->map;
  1075. + if (map->type == _DRM_FRAME_BUFFER) {
  1076. + map->handle = ioremap_nocache(map->offset, map->size);
  1077. + if (!map->handle) {
  1078. + CIRRUS_ERROR("fb: can't remap framebuffer\n");
  1079. + return -1;
  1080. + }
  1081. + break;
  1082. + }
  1083. + }
  1084. +
  1085. + info->fix.smem_start = map->offset;
  1086. + info->fix.smem_len = map->size;
  1087. + if (!info->fix.smem_len) {
  1088. + CIRRUS_ERROR("%s: can't count memory\n", info->fix.id);
  1089. + goto out_iounmap;
  1090. + }
  1091. + info->screen_base = map->handle;
  1092. + if (!info->screen_base) {
  1093. + CIRRUS_ERROR("%s: can't remap framebuffer\n", info->fix.id);
  1094. + goto out_iounmap;
  1095. + }
  1096. +
  1097. + info->fix.mmio_start = 0;
  1098. + info->fix.mmio_len = 0;
  1099. +
  1100. + ret = fb_alloc_cmap(&info->cmap, 256, 0);
  1101. + if (ret) {
  1102. + CIRRUS_ERROR("%s: can't allocate color map\n", info->fix.id);
  1103. + ret = -ENOMEM;
  1104. + goto out_iounmap;
  1105. + }
  1106. +
  1107. + return 0;
  1108. +out_iounmap:
  1109. + iounmap(map->handle);
  1110. + return ret;
  1111. +}
  1112. +
  1113. +static int cirrus_fb_find_or_create_single(struct drm_fb_helper *helper,
  1114. + struct drm_fb_helper_surface_size
  1115. + *sizes)
  1116. +{
  1117. + struct cirrus_fbdev *gfbdev = (struct cirrus_fbdev *)helper;
  1118. + int new_fb = 0;
  1119. + int ret;
  1120. +
  1121. + if (!helper->fb) {
  1122. + ret = cirrusfb_create(gfbdev, sizes);
  1123. + if (ret)
  1124. + return ret;
  1125. + new_fb = 1;
  1126. + }
  1127. + return new_fb;
  1128. +}
  1129. +
  1130. +static int cirrus_fbdev_destroy(struct drm_device *dev,
  1131. + struct cirrus_fbdev *gfbdev)
  1132. +{
  1133. + struct fb_info *info;
  1134. + struct cirrus_framebuffer *gfb = &gfbdev->gfb;
  1135. +
  1136. + if (gfbdev->helper.fbdev) {
  1137. + info = gfbdev->helper.fbdev;
  1138. +
  1139. + unregister_framebuffer(info);
  1140. + if (info->cmap.len)
  1141. + fb_dealloc_cmap(&info->cmap);
  1142. + framebuffer_release(info);
  1143. + }
  1144. +
  1145. + drm_fb_helper_fini(&gfbdev->helper);
  1146. + drm_framebuffer_cleanup(&gfb->base);
  1147. +
  1148. + return 0;
  1149. +}
  1150. +
  1151. +static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
  1152. + .gamma_set = cirrus_crtc_fb_gamma_set,
  1153. + .gamma_get = cirrus_crtc_fb_gamma_get,
  1154. + .fb_probe = cirrus_fb_find_or_create_single,
  1155. +};
  1156. +
  1157. +int cirrus_fbdev_init(struct cirrus_device *cdev)
  1158. +{
  1159. + struct cirrus_fbdev *gfbdev;
  1160. + int ret;
  1161. +
  1162. + gfbdev = kzalloc(sizeof(struct cirrus_fbdev), GFP_KERNEL);
  1163. + if (!gfbdev)
  1164. + return -ENOMEM;
  1165. +
  1166. + gfbdev->cdev = cdev;
  1167. + cdev->mode_info.gfbdev = gfbdev;
  1168. + gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
  1169. +
  1170. + ret = drm_fb_helper_init(cdev->ddev, &gfbdev->helper,
  1171. + cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
  1172. + if (ret) {
  1173. + kfree(gfbdev);
  1174. + return ret;
  1175. + }
  1176. + drm_fb_helper_single_add_all_connectors(&gfbdev->helper);
  1177. + drm_fb_helper_initial_config(&gfbdev->helper, 24);
  1178. +
  1179. + return 0;
  1180. +}
  1181. +
  1182. +void cirrus_fbdev_fini(struct cirrus_device *cdev)
  1183. +{
  1184. + if (!cdev->mode_info.gfbdev)
  1185. + return;
  1186. +
  1187. + cirrus_fbdev_destroy(cdev->ddev, cdev->mode_info.gfbdev);
  1188. + kfree(cdev->mode_info.gfbdev);
  1189. + cdev->mode_info.gfbdev = NULL;
  1190. +}
  1191. diff --git a/drivers/gpu/drm/cirrus/cirrus_framebuffer.c b/drivers/gpu/drm/cirrus/cirrus_framebuffer.c
  1192. new file mode 100644
  1193. index 0000000..6cc49f2
  1194. --- /dev/null
  1195. +++ b/drivers/gpu/drm/cirrus/cirrus_framebuffer.c
  1196. @@ -0,0 +1,48 @@
  1197. +/*
  1198. + * Copyright 2010 Matt Turner.
  1199. + * Copyright 2011 Red Hat <mjg@redhat.com>
  1200. + *
  1201. + * This file is subject to the terms and conditions of the GNU General
  1202. + * Public License version 2. See the file COPYING in the main
  1203. + * directory of this archive for more details.
  1204. + *
  1205. + * Authors: Matthew Garrett
  1206. + * Matt Turner
  1207. + */
  1208. +#include "drmP.h"
  1209. +#include "drm.h"
  1210. +#include "drm_crtc_helper.h"
  1211. +
  1212. +#include "cirrus.h"
  1213. +#include "cirrus_drv.h"
  1214. +
  1215. +static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
  1216. +{
  1217. + drm_framebuffer_cleanup(fb);
  1218. +}
  1219. +
  1220. +static int cirrus_user_framebuffer_create_handle(struct drm_framebuffer *fb,
  1221. + struct drm_file *file_priv,
  1222. + unsigned int *handle)
  1223. +{
  1224. + return 0;
  1225. +}
  1226. +
  1227. +static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
  1228. + .destroy = cirrus_user_framebuffer_destroy,
  1229. + .create_handle = cirrus_user_framebuffer_create_handle,
  1230. +};
  1231. +
  1232. +int cirrus_framebuffer_init(struct drm_device *dev,
  1233. + struct cirrus_framebuffer *gfb,
  1234. + struct drm_mode_fb_cmd *mode_cmd)
  1235. +{
  1236. + int ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
  1237. + if (ret) {
  1238. + CIRRUS_ERROR("drm_framebuffer_init failed: %d\n", ret);
  1239. + return ret;
  1240. + }
  1241. + drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
  1242. +
  1243. + return 0;
  1244. +}
  1245. diff --git a/drivers/gpu/drm/cirrus/cirrus_kms.c b/drivers/gpu/drm/cirrus/cirrus_kms.c
  1246. new file mode 100644
  1247. index 0000000..967033a
  1248. --- /dev/null
  1249. +++ b/drivers/gpu/drm/cirrus/cirrus_kms.c
  1250. @@ -0,0 +1,59 @@
  1251. +/*
  1252. + * Copyright 2010 Matt Turner.
  1253. + * Copyright 2011 Red Hat <mjg@redhat.com>
  1254. + *
  1255. + * This file is subject to the terms and conditions of the GNU General
  1256. + * Public License version 2. See the file COPYING in the main
  1257. + * directory of this archive for more details.
  1258. + *
  1259. + * Authors: Matthew Garrett
  1260. + * Matt Turner
  1261. + */
  1262. +#include "drmP.h"
  1263. +#include "drm.h"
  1264. +
  1265. +#include "cirrus.h"
  1266. +#include "cirrus_drv.h"
  1267. +
  1268. +/*
  1269. + * Functions here will be called by the core once it's bound the driver to
  1270. + * a PCI device
  1271. + */
  1272. +
  1273. +int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
  1274. +{
  1275. + struct cirrus_device *cdev;
  1276. + int r;
  1277. +
  1278. + cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
  1279. + if (cdev == NULL)
  1280. + return -ENOMEM;
  1281. + dev->dev_private = (void *)cdev;
  1282. +
  1283. + r = cirrus_device_init(cdev, dev, dev->pdev, flags);
  1284. + if (r) {
  1285. + dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
  1286. + goto out;
  1287. + }
  1288. +
  1289. + r = cirrus_modeset_init(cdev);
  1290. + if (r)
  1291. + dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
  1292. +out:
  1293. + if (r)
  1294. + cirrus_driver_unload(dev);
  1295. + return r;
  1296. +}
  1297. +
  1298. +int cirrus_driver_unload(struct drm_device *dev)
  1299. +{
  1300. + struct cirrus_device *cdev = dev->dev_private;
  1301. +
  1302. + if (cdev == NULL)
  1303. + return 0;
  1304. + cirrus_modeset_fini(cdev);
  1305. + cirrus_device_fini(cdev);
  1306. + kfree(cdev);
  1307. + dev->dev_private = NULL;
  1308. + return 0;
  1309. +}
  1310. diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.h b/drivers/gpu/drm/cirrus/cirrus_mode.h
  1311. new file mode 100644
  1312. index 0000000..fec62ea
  1313. --- /dev/null
  1314. +++ b/drivers/gpu/drm/cirrus/cirrus_mode.h
  1315. @@ -0,0 +1,54 @@
  1316. +/*
  1317. + * Copyright 2010 Matt Turner.
  1318. + * Copyright 2011 Red Hat <mjg@redhat.com>
  1319. + *
  1320. + * This file is subject to the terms and conditions of the GNU General
  1321. + * Public License version 2. See the file COPYING in the main
  1322. + * directory of this archive for more details.
  1323. + *
  1324. + * Authors: Matthew Garrett
  1325. + * Matt Turner
  1326. + */
  1327. +#ifndef __CIRRUS_MODE_H__
  1328. +#define __CIRRUS_MODE_H__
  1329. +
  1330. +#include "drmP.h"
  1331. +#include "drm.h"
  1332. +
  1333. +#define CIRRUS_MAX_FB_HEIGHT 4096
  1334. +#define CIRRUS_MAX_FB_WIDTH 4096
  1335. +
  1336. +#define CIRRUS_DPMS_CLEARED (-1)
  1337. +
  1338. +#define to_cirrus_crtc(x) container_of(x, struct cirrus_crtc, base)
  1339. +#define to_cirrus_encoder(x) container_of(x, struct cirrus_encoder, base)
  1340. +#define to_cirrus_framebuffer(x) container_of(x, struct cirrus_framebuffer, base)
  1341. +
  1342. +struct cirrus_crtc {
  1343. + struct drm_crtc base;
  1344. + u8 lut_r[256], lut_g[256], lut_b[256];
  1345. + int last_dpms;
  1346. + bool enabled;
  1347. +};
  1348. +
  1349. +struct cirrus_mode_info {
  1350. + bool mode_config_initialized;
  1351. + struct cirrus_crtc *crtc;
  1352. + /* pointer to fbdev info structure */
  1353. + struct cirrus_fbdev *gfbdev;
  1354. +};
  1355. +
  1356. +struct cirrus_encoder {
  1357. + struct drm_encoder base;
  1358. + int last_dpms;
  1359. +};
  1360. +
  1361. +struct cirrus_connector {
  1362. + struct drm_connector base;
  1363. +};
  1364. +
  1365. +struct cirrus_framebuffer {
  1366. + struct drm_framebuffer base;
  1367. +};
  1368. +
  1369. +#endif /* __CIRRUS_MODE_H__ */
  1370. diff --git a/drivers/gpu/drm/cirrus/cirrus_vga.c b/drivers/gpu/drm/cirrus/cirrus_vga.c
  1371. new file mode 100644
  1372. index 0000000..b07e086
  1373. --- /dev/null
  1374. +++ b/drivers/gpu/drm/cirrus/cirrus_vga.c
  1375. @@ -0,0 +1,102 @@
  1376. +/*
  1377. + * Copyright 2010 Matt Turner.
  1378. + * Copyright 2011 Red Hat <mjg@redhat.com>
  1379. + *
  1380. + * This file is subject to the terms and conditions of the GNU General
  1381. + * Public License version 2. See the file COPYING in the main
  1382. + * directory of this archive for more details.
  1383. + *
  1384. + * Authors: Matthew Garrett
  1385. + * Matt Turner
  1386. + */
  1387. +#include "drmP.h"
  1388. +#include "drm.h"
  1389. +#include "drm_crtc_helper.h"
  1390. +
  1391. +#include <video/cirrus.h>
  1392. +
  1393. +#include "cirrus.h"
  1394. +#include "cirrus_drv.h"
  1395. +#include "cirrus_mode.h"
  1396. +
  1397. +static int cirrus_vga_get_modes(struct drm_connector *connector)
  1398. +{
  1399. + /* Just add a static list of modes */
  1400. + drm_add_modes_noedid(connector, 640, 480);
  1401. + drm_add_modes_noedid(connector, 800, 600);
  1402. + drm_add_modes_noedid(connector, 1024, 768);
  1403. + drm_add_modes_noedid(connector, 1280, 1024);
  1404. +
  1405. + return 4;
  1406. +}
  1407. +
  1408. +static int cirrus_vga_mode_valid(struct drm_connector *connector,
  1409. + struct drm_display_mode *mode)
  1410. +{
  1411. + /* Any mode we've added is valid */
  1412. + return MODE_OK;
  1413. +}
  1414. +
  1415. +struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
  1416. + *connector)
  1417. +{
  1418. + int enc_id = connector->encoder_ids[0];
  1419. + struct drm_mode_object *obj;
  1420. + struct drm_encoder *encoder;
  1421. +
  1422. + /* pick the encoder ids */
  1423. + if (enc_id) {
  1424. + obj =
  1425. + drm_mode_object_find(connector->dev, enc_id,
  1426. + DRM_MODE_OBJECT_ENCODER);
  1427. + if (!obj)
  1428. + return NULL;
  1429. + encoder = obj_to_encoder(obj);
  1430. + return encoder;
  1431. + }
  1432. + return NULL;
  1433. +}
  1434. +
  1435. +static enum drm_connector_status cirrus_vga_detect(struct drm_connector
  1436. + *connector, bool force)
  1437. +{
  1438. + return connector_status_connected;
  1439. +}
  1440. +
  1441. +static void cirrus_connector_destroy(struct drm_connector *connector)
  1442. +{
  1443. + drm_connector_cleanup(connector);
  1444. + kfree(connector);
  1445. +}
  1446. +
  1447. +struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = {
  1448. + .get_modes = cirrus_vga_get_modes,
  1449. + .mode_valid = cirrus_vga_mode_valid,
  1450. + .best_encoder = cirrus_connector_best_encoder,
  1451. +};
  1452. +
  1453. +struct drm_connector_funcs cirrus_vga_connector_funcs = {
  1454. + .dpms = drm_helper_connector_dpms,
  1455. + .detect = cirrus_vga_detect,
  1456. + .fill_modes = drm_helper_probe_single_connector_modes,
  1457. + .destroy = cirrus_connector_destroy,
  1458. +};
  1459. +
  1460. +struct drm_connector *cirrus_vga_init(struct drm_device *dev)
  1461. +{
  1462. + struct drm_connector *connector;
  1463. + struct cirrus_connector *cirrus_connector;
  1464. +
  1465. + cirrus_connector = kzalloc(sizeof(struct cirrus_connector), GFP_KERNEL);
  1466. + if (!cirrus_connector)
  1467. + return NULL;
  1468. +
  1469. + connector = &cirrus_connector->base;
  1470. +
  1471. + drm_connector_init(dev, connector,
  1472. + &cirrus_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
  1473. +
  1474. + drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
  1475. +
  1476. + return connector;
  1477. +}
  1478. --
  1479. 1.7.4.4
  1480. --
Add Comment
Please, Sign In to add comment