2
0

blizzard.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. /*
  2. * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
  3. *
  4. * Copyright (C) 2008 Nokia Corporation
  5. * Written by Andrzej Zaborowski <andrew@openedhand.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "ui/console.h"
  22. #include "hw/display/blizzard.h"
  23. #include "ui/pixel_ops.h"
  24. typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
  25. typedef struct {
  26. uint8_t reg;
  27. uint32_t addr;
  28. int swallow;
  29. int pll;
  30. int pll_range;
  31. int pll_ctrl;
  32. uint8_t pll_mode;
  33. uint8_t clksel;
  34. int memenable;
  35. int memrefresh;
  36. uint8_t timing[3];
  37. int priority;
  38. uint8_t lcd_config;
  39. int x;
  40. int y;
  41. int skipx;
  42. int skipy;
  43. uint8_t hndp;
  44. uint8_t vndp;
  45. uint8_t hsync;
  46. uint8_t vsync;
  47. uint8_t pclk;
  48. uint8_t u;
  49. uint8_t v;
  50. uint8_t yrc[2];
  51. int ix[2];
  52. int iy[2];
  53. int ox[2];
  54. int oy[2];
  55. int enable;
  56. int blank;
  57. int bpp;
  58. int invalidate;
  59. int mx[2];
  60. int my[2];
  61. uint8_t mode;
  62. uint8_t effect;
  63. uint8_t iformat;
  64. uint8_t source;
  65. QemuConsole *con;
  66. blizzard_fn_t *line_fn_tab[2];
  67. void *fb;
  68. uint8_t hssi_config[3];
  69. uint8_t tv_config;
  70. uint8_t tv_timing[4];
  71. uint8_t vbi;
  72. uint8_t tv_x;
  73. uint8_t tv_y;
  74. uint8_t tv_test;
  75. uint8_t tv_filter_config;
  76. uint8_t tv_filter_idx;
  77. uint8_t tv_filter_coeff[0x20];
  78. uint8_t border_r;
  79. uint8_t border_g;
  80. uint8_t border_b;
  81. uint8_t gamma_config;
  82. uint8_t gamma_idx;
  83. uint8_t gamma_lut[0x100];
  84. uint8_t matrix_ena;
  85. uint8_t matrix_coeff[0x12];
  86. uint8_t matrix_r;
  87. uint8_t matrix_g;
  88. uint8_t matrix_b;
  89. uint8_t pm;
  90. uint8_t status;
  91. uint8_t rgbgpio_dir;
  92. uint8_t rgbgpio;
  93. uint8_t gpio_dir;
  94. uint8_t gpio;
  95. uint8_t gpio_edge[2];
  96. uint8_t gpio_irq;
  97. uint8_t gpio_pdown;
  98. struct {
  99. int x;
  100. int y;
  101. int dx;
  102. int dy;
  103. int len;
  104. int buflen;
  105. void *buf;
  106. void *data;
  107. uint16_t *ptr;
  108. int angle;
  109. int pitch;
  110. blizzard_fn_t line_fn;
  111. } data;
  112. } BlizzardState;
  113. /* Bytes(!) per pixel */
  114. static const int blizzard_iformat_bpp[0x10] = {
  115. 0,
  116. 2, /* RGB 5:6:5*/
  117. 3, /* RGB 6:6:6 mode 1 */
  118. 3, /* RGB 8:8:8 mode 1 */
  119. 0, 0,
  120. 4, /* RGB 6:6:6 mode 2 */
  121. 4, /* RGB 8:8:8 mode 2 */
  122. 0, /* YUV 4:2:2 */
  123. 0, /* YUV 4:2:0 */
  124. 0, 0, 0, 0, 0, 0,
  125. };
  126. static void blizzard_window(BlizzardState *s)
  127. {
  128. DisplaySurface *surface = qemu_console_surface(s->con);
  129. uint8_t *src, *dst;
  130. int bypp[2];
  131. int bypl[3];
  132. int y;
  133. blizzard_fn_t fn = s->data.line_fn;
  134. if (!fn)
  135. return;
  136. if (s->mx[0] > s->data.x)
  137. s->mx[0] = s->data.x;
  138. if (s->my[0] > s->data.y)
  139. s->my[0] = s->data.y;
  140. if (s->mx[1] < s->data.x + s->data.dx)
  141. s->mx[1] = s->data.x + s->data.dx;
  142. if (s->my[1] < s->data.y + s->data.dy)
  143. s->my[1] = s->data.y + s->data.dy;
  144. bypp[0] = s->bpp;
  145. bypp[1] = surface_bytes_per_pixel(surface);
  146. bypl[0] = bypp[0] * s->data.pitch;
  147. bypl[1] = bypp[1] * s->x;
  148. bypl[2] = bypp[0] * s->data.dx;
  149. src = s->data.data;
  150. dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x;
  151. for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1])
  152. fn(dst, src, bypl[2]);
  153. }
  154. static int blizzard_transfer_setup(BlizzardState *s)
  155. {
  156. if (s->source > 3 || !s->bpp ||
  157. s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0])
  158. return 0;
  159. s->data.angle = s->effect & 3;
  160. s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat];
  161. s->data.x = s->ix[0];
  162. s->data.y = s->iy[0];
  163. s->data.dx = s->ix[1] - s->ix[0] + 1;
  164. s->data.dy = s->iy[1] - s->iy[0] + 1;
  165. s->data.len = s->bpp * s->data.dx * s->data.dy;
  166. s->data.pitch = s->data.dx;
  167. if (s->data.len > s->data.buflen) {
  168. s->data.buf = g_realloc(s->data.buf, s->data.len);
  169. s->data.buflen = s->data.len;
  170. }
  171. s->data.ptr = s->data.buf;
  172. s->data.data = s->data.buf;
  173. s->data.len /= 2;
  174. return 1;
  175. }
  176. static void blizzard_reset(BlizzardState *s)
  177. {
  178. s->reg = 0;
  179. s->swallow = 0;
  180. s->pll = 9;
  181. s->pll_range = 1;
  182. s->pll_ctrl = 0x14;
  183. s->pll_mode = 0x32;
  184. s->clksel = 0x00;
  185. s->memenable = 0;
  186. s->memrefresh = 0x25c;
  187. s->timing[0] = 0x3f;
  188. s->timing[1] = 0x13;
  189. s->timing[2] = 0x21;
  190. s->priority = 0;
  191. s->lcd_config = 0x74;
  192. s->x = 8;
  193. s->y = 1;
  194. s->skipx = 0;
  195. s->skipy = 0;
  196. s->hndp = 3;
  197. s->vndp = 2;
  198. s->hsync = 1;
  199. s->vsync = 1;
  200. s->pclk = 0x80;
  201. s->ix[0] = 0;
  202. s->ix[1] = 0;
  203. s->iy[0] = 0;
  204. s->iy[1] = 0;
  205. s->ox[0] = 0;
  206. s->ox[1] = 0;
  207. s->oy[0] = 0;
  208. s->oy[1] = 0;
  209. s->yrc[0] = 0x00;
  210. s->yrc[1] = 0x30;
  211. s->u = 0;
  212. s->v = 0;
  213. s->iformat = 3;
  214. s->source = 0;
  215. s->bpp = blizzard_iformat_bpp[s->iformat];
  216. s->hssi_config[0] = 0x00;
  217. s->hssi_config[1] = 0x00;
  218. s->hssi_config[2] = 0x01;
  219. s->tv_config = 0x00;
  220. s->tv_timing[0] = 0x00;
  221. s->tv_timing[1] = 0x00;
  222. s->tv_timing[2] = 0x00;
  223. s->tv_timing[3] = 0x00;
  224. s->vbi = 0x10;
  225. s->tv_x = 0x14;
  226. s->tv_y = 0x03;
  227. s->tv_test = 0x00;
  228. s->tv_filter_config = 0x80;
  229. s->tv_filter_idx = 0x00;
  230. s->border_r = 0x10;
  231. s->border_g = 0x80;
  232. s->border_b = 0x80;
  233. s->gamma_config = 0x00;
  234. s->gamma_idx = 0x00;
  235. s->matrix_ena = 0x00;
  236. memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff));
  237. s->matrix_r = 0x00;
  238. s->matrix_g = 0x00;
  239. s->matrix_b = 0x00;
  240. s->pm = 0x02;
  241. s->status = 0x00;
  242. s->rgbgpio_dir = 0x00;
  243. s->gpio_dir = 0x00;
  244. s->gpio_edge[0] = 0x00;
  245. s->gpio_edge[1] = 0x00;
  246. s->gpio_irq = 0x00;
  247. s->gpio_pdown = 0xff;
  248. }
  249. static inline void blizzard_invalidate_display(void *opaque) {
  250. BlizzardState *s = (BlizzardState *) opaque;
  251. s->invalidate = 1;
  252. }
  253. static uint16_t blizzard_reg_read(void *opaque, uint8_t reg)
  254. {
  255. BlizzardState *s = (BlizzardState *) opaque;
  256. switch (reg) {
  257. case 0x00: /* Revision Code */
  258. return 0xa5;
  259. case 0x02: /* Configuration Readback */
  260. return 0x83; /* Macrovision OK, CNF[2:0] = 3 */
  261. case 0x04: /* PLL M-Divider */
  262. return (s->pll - 1) | (1 << 7);
  263. case 0x06: /* PLL Lock Range Control */
  264. return s->pll_range;
  265. case 0x08: /* PLL Lock Synthesis Control 0 */
  266. return s->pll_ctrl & 0xff;
  267. case 0x0a: /* PLL Lock Synthesis Control 1 */
  268. return s->pll_ctrl >> 8;
  269. case 0x0c: /* PLL Mode Control 0 */
  270. return s->pll_mode;
  271. case 0x0e: /* Clock-Source Select */
  272. return s->clksel;
  273. case 0x10: /* Memory Controller Activate */
  274. case 0x14: /* Memory Controller Bank 0 Status Flag */
  275. return s->memenable;
  276. case 0x18: /* Auto-Refresh Interval Setting 0 */
  277. return s->memrefresh & 0xff;
  278. case 0x1a: /* Auto-Refresh Interval Setting 1 */
  279. return s->memrefresh >> 8;
  280. case 0x1c: /* Power-On Sequence Timing Control */
  281. return s->timing[0];
  282. case 0x1e: /* Timing Control 0 */
  283. return s->timing[1];
  284. case 0x20: /* Timing Control 1 */
  285. return s->timing[2];
  286. case 0x24: /* Arbitration Priority Control */
  287. return s->priority;
  288. case 0x28: /* LCD Panel Configuration */
  289. return s->lcd_config;
  290. case 0x2a: /* LCD Horizontal Display Width */
  291. return s->x >> 3;
  292. case 0x2c: /* LCD Horizontal Non-display Period */
  293. return s->hndp;
  294. case 0x2e: /* LCD Vertical Display Height 0 */
  295. return s->y & 0xff;
  296. case 0x30: /* LCD Vertical Display Height 1 */
  297. return s->y >> 8;
  298. case 0x32: /* LCD Vertical Non-display Period */
  299. return s->vndp;
  300. case 0x34: /* LCD HS Pulse-width */
  301. return s->hsync;
  302. case 0x36: /* LCd HS Pulse Start Position */
  303. return s->skipx >> 3;
  304. case 0x38: /* LCD VS Pulse-width */
  305. return s->vsync;
  306. case 0x3a: /* LCD VS Pulse Start Position */
  307. return s->skipy;
  308. case 0x3c: /* PCLK Polarity */
  309. return s->pclk;
  310. case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */
  311. return s->hssi_config[0];
  312. case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */
  313. return s->hssi_config[1];
  314. case 0x42: /* High-speed Serial Interface Tx Mode */
  315. return s->hssi_config[2];
  316. case 0x44: /* TV Display Configuration */
  317. return s->tv_config;
  318. case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits */
  319. return s->tv_timing[(reg - 0x46) >> 1];
  320. case 0x4e: /* VBI: Closed Caption / XDS Control / Status */
  321. return s->vbi;
  322. case 0x50: /* TV Horizontal Start Position */
  323. return s->tv_x;
  324. case 0x52: /* TV Vertical Start Position */
  325. return s->tv_y;
  326. case 0x54: /* TV Test Pattern Setting */
  327. return s->tv_test;
  328. case 0x56: /* TV Filter Setting */
  329. return s->tv_filter_config;
  330. case 0x58: /* TV Filter Coefficient Index */
  331. return s->tv_filter_idx;
  332. case 0x5a: /* TV Filter Coefficient Data */
  333. if (s->tv_filter_idx < 0x20)
  334. return s->tv_filter_coeff[s->tv_filter_idx ++];
  335. return 0;
  336. case 0x60: /* Input YUV/RGB Translate Mode 0 */
  337. return s->yrc[0];
  338. case 0x62: /* Input YUV/RGB Translate Mode 1 */
  339. return s->yrc[1];
  340. case 0x64: /* U Data Fix */
  341. return s->u;
  342. case 0x66: /* V Data Fix */
  343. return s->v;
  344. case 0x68: /* Display Mode */
  345. return s->mode;
  346. case 0x6a: /* Special Effects */
  347. return s->effect;
  348. case 0x6c: /* Input Window X Start Position 0 */
  349. return s->ix[0] & 0xff;
  350. case 0x6e: /* Input Window X Start Position 1 */
  351. return s->ix[0] >> 3;
  352. case 0x70: /* Input Window Y Start Position 0 */
  353. return s->ix[0] & 0xff;
  354. case 0x72: /* Input Window Y Start Position 1 */
  355. return s->ix[0] >> 3;
  356. case 0x74: /* Input Window X End Position 0 */
  357. return s->ix[1] & 0xff;
  358. case 0x76: /* Input Window X End Position 1 */
  359. return s->ix[1] >> 3;
  360. case 0x78: /* Input Window Y End Position 0 */
  361. return s->ix[1] & 0xff;
  362. case 0x7a: /* Input Window Y End Position 1 */
  363. return s->ix[1] >> 3;
  364. case 0x7c: /* Output Window X Start Position 0 */
  365. return s->ox[0] & 0xff;
  366. case 0x7e: /* Output Window X Start Position 1 */
  367. return s->ox[0] >> 3;
  368. case 0x80: /* Output Window Y Start Position 0 */
  369. return s->oy[0] & 0xff;
  370. case 0x82: /* Output Window Y Start Position 1 */
  371. return s->oy[0] >> 3;
  372. case 0x84: /* Output Window X End Position 0 */
  373. return s->ox[1] & 0xff;
  374. case 0x86: /* Output Window X End Position 1 */
  375. return s->ox[1] >> 3;
  376. case 0x88: /* Output Window Y End Position 0 */
  377. return s->oy[1] & 0xff;
  378. case 0x8a: /* Output Window Y End Position 1 */
  379. return s->oy[1] >> 3;
  380. case 0x8c: /* Input Data Format */
  381. return s->iformat;
  382. case 0x8e: /* Data Source Select */
  383. return s->source;
  384. case 0x90: /* Display Memory Data Port */
  385. return 0;
  386. case 0xa8: /* Border Color 0 */
  387. return s->border_r;
  388. case 0xaa: /* Border Color 1 */
  389. return s->border_g;
  390. case 0xac: /* Border Color 2 */
  391. return s->border_b;
  392. case 0xb4: /* Gamma Correction Enable */
  393. return s->gamma_config;
  394. case 0xb6: /* Gamma Correction Table Index */
  395. return s->gamma_idx;
  396. case 0xb8: /* Gamma Correction Table Data */
  397. return s->gamma_lut[s->gamma_idx ++];
  398. case 0xba: /* 3x3 Matrix Enable */
  399. return s->matrix_ena;
  400. case 0xbc ... 0xde: /* Coefficient Registers */
  401. return s->matrix_coeff[(reg - 0xbc) >> 1];
  402. case 0xe0: /* 3x3 Matrix Red Offset */
  403. return s->matrix_r;
  404. case 0xe2: /* 3x3 Matrix Green Offset */
  405. return s->matrix_g;
  406. case 0xe4: /* 3x3 Matrix Blue Offset */
  407. return s->matrix_b;
  408. case 0xe6: /* Power-save */
  409. return s->pm;
  410. case 0xe8: /* Non-display Period Control / Status */
  411. return s->status | (1 << 5);
  412. case 0xea: /* RGB Interface Control */
  413. return s->rgbgpio_dir;
  414. case 0xec: /* RGB Interface Status */
  415. return s->rgbgpio;
  416. case 0xee: /* General-purpose IO Pins Configuration */
  417. return s->gpio_dir;
  418. case 0xf0: /* General-purpose IO Pins Status / Control */
  419. return s->gpio;
  420. case 0xf2: /* GPIO Positive Edge Interrupt Trigger */
  421. return s->gpio_edge[0];
  422. case 0xf4: /* GPIO Negative Edge Interrupt Trigger */
  423. return s->gpio_edge[1];
  424. case 0xf6: /* GPIO Interrupt Status */
  425. return s->gpio_irq;
  426. case 0xf8: /* GPIO Pull-down Control */
  427. return s->gpio_pdown;
  428. default:
  429. fprintf(stderr, "%s: unknown register %02x\n", __func__, reg);
  430. return 0;
  431. }
  432. }
  433. static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value)
  434. {
  435. BlizzardState *s = (BlizzardState *) opaque;
  436. switch (reg) {
  437. case 0x04: /* PLL M-Divider */
  438. s->pll = (value & 0x3f) + 1;
  439. break;
  440. case 0x06: /* PLL Lock Range Control */
  441. s->pll_range = value & 3;
  442. break;
  443. case 0x08: /* PLL Lock Synthesis Control 0 */
  444. s->pll_ctrl &= 0xf00;
  445. s->pll_ctrl |= (value << 0) & 0x0ff;
  446. break;
  447. case 0x0a: /* PLL Lock Synthesis Control 1 */
  448. s->pll_ctrl &= 0x0ff;
  449. s->pll_ctrl |= (value << 8) & 0xf00;
  450. break;
  451. case 0x0c: /* PLL Mode Control 0 */
  452. s->pll_mode = value & 0x77;
  453. if ((value & 3) == 0 || (value & 3) == 3)
  454. fprintf(stderr, "%s: wrong PLL Control bits (%i)\n",
  455. __func__, value & 3);
  456. break;
  457. case 0x0e: /* Clock-Source Select */
  458. s->clksel = value & 0xff;
  459. break;
  460. case 0x10: /* Memory Controller Activate */
  461. s->memenable = value & 1;
  462. break;
  463. case 0x14: /* Memory Controller Bank 0 Status Flag */
  464. break;
  465. case 0x18: /* Auto-Refresh Interval Setting 0 */
  466. s->memrefresh &= 0xf00;
  467. s->memrefresh |= (value << 0) & 0x0ff;
  468. break;
  469. case 0x1a: /* Auto-Refresh Interval Setting 1 */
  470. s->memrefresh &= 0x0ff;
  471. s->memrefresh |= (value << 8) & 0xf00;
  472. break;
  473. case 0x1c: /* Power-On Sequence Timing Control */
  474. s->timing[0] = value & 0x7f;
  475. break;
  476. case 0x1e: /* Timing Control 0 */
  477. s->timing[1] = value & 0x17;
  478. break;
  479. case 0x20: /* Timing Control 1 */
  480. s->timing[2] = value & 0x35;
  481. break;
  482. case 0x24: /* Arbitration Priority Control */
  483. s->priority = value & 1;
  484. break;
  485. case 0x28: /* LCD Panel Configuration */
  486. s->lcd_config = value & 0xff;
  487. if (value & (1 << 7))
  488. fprintf(stderr, "%s: data swap not supported!\n", __func__);
  489. break;
  490. case 0x2a: /* LCD Horizontal Display Width */
  491. s->x = value << 3;
  492. break;
  493. case 0x2c: /* LCD Horizontal Non-display Period */
  494. s->hndp = value & 0xff;
  495. break;
  496. case 0x2e: /* LCD Vertical Display Height 0 */
  497. s->y &= 0x300;
  498. s->y |= (value << 0) & 0x0ff;
  499. break;
  500. case 0x30: /* LCD Vertical Display Height 1 */
  501. s->y &= 0x0ff;
  502. s->y |= (value << 8) & 0x300;
  503. break;
  504. case 0x32: /* LCD Vertical Non-display Period */
  505. s->vndp = value & 0xff;
  506. break;
  507. case 0x34: /* LCD HS Pulse-width */
  508. s->hsync = value & 0xff;
  509. break;
  510. case 0x36: /* LCD HS Pulse Start Position */
  511. s->skipx = value & 0xff;
  512. break;
  513. case 0x38: /* LCD VS Pulse-width */
  514. s->vsync = value & 0xbf;
  515. break;
  516. case 0x3a: /* LCD VS Pulse Start Position */
  517. s->skipy = value & 0xff;
  518. break;
  519. case 0x3c: /* PCLK Polarity */
  520. s->pclk = value & 0x82;
  521. /* Affects calculation of s->hndp, s->hsync and s->skipx. */
  522. break;
  523. case 0x3e: /* High-speed Serial Interface Tx Configuration Port 0 */
  524. s->hssi_config[0] = value;
  525. break;
  526. case 0x40: /* High-speed Serial Interface Tx Configuration Port 1 */
  527. s->hssi_config[1] = value;
  528. if (((value >> 4) & 3) == 3)
  529. fprintf(stderr, "%s: Illegal active-data-links value\n",
  530. __func__);
  531. break;
  532. case 0x42: /* High-speed Serial Interface Tx Mode */
  533. s->hssi_config[2] = value & 0xbd;
  534. break;
  535. case 0x44: /* TV Display Configuration */
  536. s->tv_config = value & 0xfe;
  537. break;
  538. case 0x46 ... 0x4c: /* TV Vertical Blanking Interval Data bits 0 */
  539. s->tv_timing[(reg - 0x46) >> 1] = value;
  540. break;
  541. case 0x4e: /* VBI: Closed Caption / XDS Control / Status */
  542. s->vbi = value;
  543. break;
  544. case 0x50: /* TV Horizontal Start Position */
  545. s->tv_x = value;
  546. break;
  547. case 0x52: /* TV Vertical Start Position */
  548. s->tv_y = value & 0x7f;
  549. break;
  550. case 0x54: /* TV Test Pattern Setting */
  551. s->tv_test = value;
  552. break;
  553. case 0x56: /* TV Filter Setting */
  554. s->tv_filter_config = value & 0xbf;
  555. break;
  556. case 0x58: /* TV Filter Coefficient Index */
  557. s->tv_filter_idx = value & 0x1f;
  558. break;
  559. case 0x5a: /* TV Filter Coefficient Data */
  560. if (s->tv_filter_idx < 0x20)
  561. s->tv_filter_coeff[s->tv_filter_idx ++] = value;
  562. break;
  563. case 0x60: /* Input YUV/RGB Translate Mode 0 */
  564. s->yrc[0] = value & 0xb0;
  565. break;
  566. case 0x62: /* Input YUV/RGB Translate Mode 1 */
  567. s->yrc[1] = value & 0x30;
  568. break;
  569. case 0x64: /* U Data Fix */
  570. s->u = value & 0xff;
  571. break;
  572. case 0x66: /* V Data Fix */
  573. s->v = value & 0xff;
  574. break;
  575. case 0x68: /* Display Mode */
  576. if ((s->mode ^ value) & 3)
  577. s->invalidate = 1;
  578. s->mode = value & 0xb7;
  579. s->enable = value & 1;
  580. s->blank = (value >> 1) & 1;
  581. if (value & (1 << 4))
  582. fprintf(stderr, "%s: Macrovision enable attempt!\n", __func__);
  583. break;
  584. case 0x6a: /* Special Effects */
  585. s->effect = value & 0xfb;
  586. break;
  587. case 0x6c: /* Input Window X Start Position 0 */
  588. s->ix[0] &= 0x300;
  589. s->ix[0] |= (value << 0) & 0x0ff;
  590. break;
  591. case 0x6e: /* Input Window X Start Position 1 */
  592. s->ix[0] &= 0x0ff;
  593. s->ix[0] |= (value << 8) & 0x300;
  594. break;
  595. case 0x70: /* Input Window Y Start Position 0 */
  596. s->iy[0] &= 0x300;
  597. s->iy[0] |= (value << 0) & 0x0ff;
  598. break;
  599. case 0x72: /* Input Window Y Start Position 1 */
  600. s->iy[0] &= 0x0ff;
  601. s->iy[0] |= (value << 8) & 0x300;
  602. break;
  603. case 0x74: /* Input Window X End Position 0 */
  604. s->ix[1] &= 0x300;
  605. s->ix[1] |= (value << 0) & 0x0ff;
  606. break;
  607. case 0x76: /* Input Window X End Position 1 */
  608. s->ix[1] &= 0x0ff;
  609. s->ix[1] |= (value << 8) & 0x300;
  610. break;
  611. case 0x78: /* Input Window Y End Position 0 */
  612. s->iy[1] &= 0x300;
  613. s->iy[1] |= (value << 0) & 0x0ff;
  614. break;
  615. case 0x7a: /* Input Window Y End Position 1 */
  616. s->iy[1] &= 0x0ff;
  617. s->iy[1] |= (value << 8) & 0x300;
  618. break;
  619. case 0x7c: /* Output Window X Start Position 0 */
  620. s->ox[0] &= 0x300;
  621. s->ox[0] |= (value << 0) & 0x0ff;
  622. break;
  623. case 0x7e: /* Output Window X Start Position 1 */
  624. s->ox[0] &= 0x0ff;
  625. s->ox[0] |= (value << 8) & 0x300;
  626. break;
  627. case 0x80: /* Output Window Y Start Position 0 */
  628. s->oy[0] &= 0x300;
  629. s->oy[0] |= (value << 0) & 0x0ff;
  630. break;
  631. case 0x82: /* Output Window Y Start Position 1 */
  632. s->oy[0] &= 0x0ff;
  633. s->oy[0] |= (value << 8) & 0x300;
  634. break;
  635. case 0x84: /* Output Window X End Position 0 */
  636. s->ox[1] &= 0x300;
  637. s->ox[1] |= (value << 0) & 0x0ff;
  638. break;
  639. case 0x86: /* Output Window X End Position 1 */
  640. s->ox[1] &= 0x0ff;
  641. s->ox[1] |= (value << 8) & 0x300;
  642. break;
  643. case 0x88: /* Output Window Y End Position 0 */
  644. s->oy[1] &= 0x300;
  645. s->oy[1] |= (value << 0) & 0x0ff;
  646. break;
  647. case 0x8a: /* Output Window Y End Position 1 */
  648. s->oy[1] &= 0x0ff;
  649. s->oy[1] |= (value << 8) & 0x300;
  650. break;
  651. case 0x8c: /* Input Data Format */
  652. s->iformat = value & 0xf;
  653. s->bpp = blizzard_iformat_bpp[s->iformat];
  654. if (!s->bpp)
  655. fprintf(stderr, "%s: Illegal or unsupported input format %x\n",
  656. __func__, s->iformat);
  657. break;
  658. case 0x8e: /* Data Source Select */
  659. s->source = value & 7;
  660. /* Currently all windows will be "destructive overlays". */
  661. if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] ||
  662. s->iy[0] != s->oy[0] ||
  663. s->ix[1] != s->ox[1] ||
  664. s->iy[1] != s->oy[1])) ||
  665. !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) &
  666. (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1))
  667. fprintf(stderr, "%s: Illegal input/output window positions\n",
  668. __func__);
  669. blizzard_transfer_setup(s);
  670. break;
  671. case 0x90: /* Display Memory Data Port */
  672. if (!s->data.len && !blizzard_transfer_setup(s))
  673. break;
  674. *s->data.ptr ++ = value;
  675. if (-- s->data.len == 0)
  676. blizzard_window(s);
  677. break;
  678. case 0xa8: /* Border Color 0 */
  679. s->border_r = value;
  680. break;
  681. case 0xaa: /* Border Color 1 */
  682. s->border_g = value;
  683. break;
  684. case 0xac: /* Border Color 2 */
  685. s->border_b = value;
  686. break;
  687. case 0xb4: /* Gamma Correction Enable */
  688. s->gamma_config = value & 0x87;
  689. break;
  690. case 0xb6: /* Gamma Correction Table Index */
  691. s->gamma_idx = value;
  692. break;
  693. case 0xb8: /* Gamma Correction Table Data */
  694. s->gamma_lut[s->gamma_idx ++] = value;
  695. break;
  696. case 0xba: /* 3x3 Matrix Enable */
  697. s->matrix_ena = value & 1;
  698. break;
  699. case 0xbc ... 0xde: /* Coefficient Registers */
  700. s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff);
  701. break;
  702. case 0xe0: /* 3x3 Matrix Red Offset */
  703. s->matrix_r = value;
  704. break;
  705. case 0xe2: /* 3x3 Matrix Green Offset */
  706. s->matrix_g = value;
  707. break;
  708. case 0xe4: /* 3x3 Matrix Blue Offset */
  709. s->matrix_b = value;
  710. break;
  711. case 0xe6: /* Power-save */
  712. s->pm = value & 0x83;
  713. if (value & s->mode & 1)
  714. fprintf(stderr, "%s: The display must be disabled before entering "
  715. "Standby Mode\n", __func__);
  716. break;
  717. case 0xe8: /* Non-display Period Control / Status */
  718. s->status = value & 0x1b;
  719. break;
  720. case 0xea: /* RGB Interface Control */
  721. s->rgbgpio_dir = value & 0x8f;
  722. break;
  723. case 0xec: /* RGB Interface Status */
  724. s->rgbgpio = value & 0xcf;
  725. break;
  726. case 0xee: /* General-purpose IO Pins Configuration */
  727. s->gpio_dir = value;
  728. break;
  729. case 0xf0: /* General-purpose IO Pins Status / Control */
  730. s->gpio = value;
  731. break;
  732. case 0xf2: /* GPIO Positive Edge Interrupt Trigger */
  733. s->gpio_edge[0] = value;
  734. break;
  735. case 0xf4: /* GPIO Negative Edge Interrupt Trigger */
  736. s->gpio_edge[1] = value;
  737. break;
  738. case 0xf6: /* GPIO Interrupt Status */
  739. s->gpio_irq &= value;
  740. break;
  741. case 0xf8: /* GPIO Pull-down Control */
  742. s->gpio_pdown = value;
  743. break;
  744. default:
  745. fprintf(stderr, "%s: unknown register %02x\n", __func__, reg);
  746. break;
  747. }
  748. }
  749. uint16_t s1d13745_read(void *opaque, int dc)
  750. {
  751. BlizzardState *s = (BlizzardState *) opaque;
  752. uint16_t value = blizzard_reg_read(s, s->reg);
  753. if (s->swallow -- > 0)
  754. return 0;
  755. if (dc)
  756. s->reg ++;
  757. return value;
  758. }
  759. void s1d13745_write(void *opaque, int dc, uint16_t value)
  760. {
  761. BlizzardState *s = (BlizzardState *) opaque;
  762. if (s->swallow -- > 0)
  763. return;
  764. if (dc) {
  765. blizzard_reg_write(s, s->reg, value);
  766. if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8)
  767. s->reg += 2;
  768. } else
  769. s->reg = value & 0xff;
  770. }
  771. void s1d13745_write_block(void *opaque, int dc,
  772. void *buf, size_t len, int pitch)
  773. {
  774. BlizzardState *s = (BlizzardState *) opaque;
  775. while (len > 0) {
  776. if (s->reg == 0x90 && dc &&
  777. (s->data.len || blizzard_transfer_setup(s)) &&
  778. len >= (s->data.len << 1)) {
  779. len -= s->data.len << 1;
  780. s->data.len = 0;
  781. s->data.data = buf;
  782. if (pitch)
  783. s->data.pitch = pitch;
  784. blizzard_window(s);
  785. s->data.data = s->data.buf;
  786. continue;
  787. }
  788. s1d13745_write(opaque, dc, *(uint16_t *) buf);
  789. len -= 2;
  790. buf += 2;
  791. }
  792. }
  793. static void blizzard_update_display(void *opaque)
  794. {
  795. BlizzardState *s = (BlizzardState *) opaque;
  796. DisplaySurface *surface = qemu_console_surface(s->con);
  797. int y, bypp, bypl, bwidth;
  798. uint8_t *src, *dst;
  799. if (!s->enable)
  800. return;
  801. if (s->x != surface_width(surface) || s->y != surface_height(surface)) {
  802. s->invalidate = 1;
  803. qemu_console_resize(s->con, s->x, s->y);
  804. surface = qemu_console_surface(s->con);
  805. }
  806. if (s->invalidate) {
  807. s->invalidate = 0;
  808. if (s->blank) {
  809. bypp = surface_bytes_per_pixel(surface);
  810. memset(surface_data(surface), 0, bypp * s->x * s->y);
  811. return;
  812. }
  813. s->mx[0] = 0;
  814. s->mx[1] = s->x;
  815. s->my[0] = 0;
  816. s->my[1] = s->y;
  817. }
  818. if (s->mx[1] <= s->mx[0])
  819. return;
  820. bypp = surface_bytes_per_pixel(surface);
  821. bypl = bypp * s->x;
  822. bwidth = bypp * (s->mx[1] - s->mx[0]);
  823. y = s->my[0];
  824. src = s->fb + bypl * y + bypp * s->mx[0];
  825. dst = surface_data(surface) + bypl * y + bypp * s->mx[0];
  826. for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
  827. memcpy(dst, src, bwidth);
  828. dpy_gfx_update(s->con, s->mx[0], s->my[0],
  829. s->mx[1] - s->mx[0], y - s->my[0]);
  830. s->mx[0] = s->x;
  831. s->mx[1] = 0;
  832. s->my[0] = s->y;
  833. s->my[1] = 0;
  834. }
  835. static void blizzard_draw_line16_32(uint32_t *dest,
  836. const uint16_t *src, unsigned int width)
  837. {
  838. uint16_t data;
  839. unsigned int r, g, b;
  840. const uint16_t *end = (const void *) src + width;
  841. while (src < end) {
  842. data = *src ++;
  843. b = (data & 0x1f) << 3;
  844. data >>= 5;
  845. g = (data & 0x3f) << 2;
  846. data >>= 6;
  847. r = (data & 0x1f) << 3;
  848. data >>= 5;
  849. *dest++ = rgb_to_pixel32(r, g, b);
  850. }
  851. }
  852. static void blizzard_draw_line24mode1_32(uint32_t *dest,
  853. const uint8_t *src, unsigned int width)
  854. {
  855. /* TODO: check if SDL 24-bit planes are not in the same format and
  856. * if so, use memcpy */
  857. unsigned int r[2], g[2], b[2];
  858. const uint8_t *end = src + width;
  859. while (src < end) {
  860. g[0] = *src ++;
  861. r[0] = *src ++;
  862. r[1] = *src ++;
  863. b[0] = *src ++;
  864. *dest++ = rgb_to_pixel32(r[0], g[0], b[0]);
  865. b[1] = *src ++;
  866. g[1] = *src ++;
  867. *dest++ = rgb_to_pixel32(r[1], g[1], b[1]);
  868. }
  869. }
  870. static void blizzard_draw_line24mode2_32(uint32_t *dest,
  871. const uint8_t *src, unsigned int width)
  872. {
  873. unsigned int r, g, b;
  874. const uint8_t *end = src + width;
  875. while (src < end) {
  876. r = *src ++;
  877. src ++;
  878. b = *src ++;
  879. g = *src ++;
  880. *dest++ = rgb_to_pixel32(r, g, b);
  881. }
  882. }
  883. /* No rotation */
  884. static blizzard_fn_t blizzard_draw_fn_32[0x10] = {
  885. NULL,
  886. /* RGB 5:6:5*/
  887. (blizzard_fn_t) blizzard_draw_line16_32,
  888. /* RGB 6:6:6 mode 1 */
  889. (blizzard_fn_t) blizzard_draw_line24mode1_32,
  890. /* RGB 8:8:8 mode 1 */
  891. (blizzard_fn_t) blizzard_draw_line24mode1_32,
  892. NULL, NULL,
  893. /* RGB 6:6:6 mode 2 */
  894. (blizzard_fn_t) blizzard_draw_line24mode2_32,
  895. /* RGB 8:8:8 mode 2 */
  896. (blizzard_fn_t) blizzard_draw_line24mode2_32,
  897. /* YUV 4:2:2 */
  898. NULL,
  899. /* YUV 4:2:0 */
  900. NULL,
  901. NULL, NULL, NULL, NULL, NULL, NULL,
  902. };
  903. /* 90deg, 180deg and 270deg rotation */
  904. static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = {
  905. /* TODO */
  906. [0 ... 0xf] = NULL,
  907. };
  908. static const GraphicHwOps blizzard_ops = {
  909. .invalidate = blizzard_invalidate_display,
  910. .gfx_update = blizzard_update_display,
  911. };
  912. void *s1d13745_init(qemu_irq gpio_int)
  913. {
  914. BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s));
  915. DisplaySurface *surface;
  916. s->fb = g_malloc(0x180000);
  917. s->con = graphic_console_init(NULL, 0, &blizzard_ops, s);
  918. surface = qemu_console_surface(s->con);
  919. assert(surface_bits_per_pixel(surface) == 32);
  920. s->line_fn_tab[0] = blizzard_draw_fn_32;
  921. s->line_fn_tab[1] = blizzard_draw_fn_r_32;
  922. blizzard_reset(s);
  923. return s;
  924. }