blob: 41822c6c0380fa1da2456adad317b3e731e8a4d7 [file] [log] [blame]
Sudip Mukherjee81dee672015-03-03 16:21:06 +05301#include <linux/version.h>
Mike Rapoport67088d42015-09-22 12:01:16 +03002#include <linux/module.h>
3#include <linux/kernel.h>
4#include <linux/errno.h>
5#include <linux/string.h>
6#include <linux/mm.h>
7#include <linux/slab.h>
8#include <linux/delay.h>
9#include <linux/fb.h>
10#include <linux/ioport.h>
11#include <linux/init.h>
12#include <linux/pci.h>
13#include <linux/vmalloc.h>
14#include <linux/pagemap.h>
Sudip Mukherjee81dee672015-03-03 16:21:06 +053015#include <linux/console.h>
16#ifdef CONFIG_MTRR
17#include <asm/mtrr.h>
18#endif
Mike Rapoport67088d42015-09-22 12:01:16 +030019#include <linux/platform_device.h>
20#include <linux/screen_info.h>
Mike Rapoport4cf26d82015-09-22 12:01:17 +030021#include <linux/sizes.h>
Sudip Mukherjee81dee672015-03-03 16:21:06 +053022
23#include "sm750.h"
Sudip Mukherjee81dee672015-03-03 16:21:06 +053024#include "ddk750.h"
25#include "sm750_accel.h"
26
Mike Rapoport700591a2015-10-26 09:06:01 +020027int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
Sudip Mukherjee81dee672015-03-03 16:21:06 +053028{
29 int ret;
Anatoly Stepanov29d87332015-06-29 02:43:55 +030030
Sudip Mukherjee81dee672015-03-03 16:21:06 +053031 ret = 0;
32
Mike Rapoporte359b6a2015-10-26 09:06:06 +020033 sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
34 sm750_dev->vidreg_size = SZ_2M;
Sudip Mukherjee81dee672015-03-03 16:21:06 +053035
Mike Rapoporte359b6a2015-10-26 09:06:06 +020036 pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053037
38 /* reserve the vidreg space of smi adaptor
39 * if you do this, u need to add release region code
40 * in lynxfb_remove, or memory will not be mapped again
41 * successfully
42 * */
Anatoly Stepanov9a52ae22015-06-29 02:44:02 +030043 ret = pci_request_region(pdev, 1, "sm750fb");
44 if (ret) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +053045 pr_err("Can not request PCI regions.\n");
46 goto exit;
47 }
48
49 /* now map mmio and vidmem*/
Mike Rapoporte359b6a2015-10-26 09:06:06 +020050 sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
51 sm750_dev->vidreg_size);
52 if (!sm750_dev->pvReg) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +053053 pr_err("mmio failed\n");
54 ret = -EFAULT;
55 goto exit;
Anatoly Stepanov5e83e282015-06-29 02:44:00 +030056 } else {
Mike Rapoporte359b6a2015-10-26 09:06:06 +020057 pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053058 }
59
Anatoly Stepanov29d87332015-06-29 02:43:55 +030060
Mike Rapoporte359b6a2015-10-26 09:06:06 +020061 sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
62 sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
Sudip Mukherjee81dee672015-03-03 16:21:06 +053063
Mike Rapoporte359b6a2015-10-26 09:06:06 +020064 ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053065
Mike Rapoporte359b6a2015-10-26 09:06:06 +020066 sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053067 /* don't use pdev_resource[x].end - resource[x].start to
68 * calculate the resource size,its only the maximum available
69 * size but not the actual size,use
Mike Rapoport142de762015-10-26 09:06:00 +020070 * @ddk750_getVMSize function can be safe.
Sudip Mukherjee81dee672015-03-03 16:21:06 +053071 * */
Mike Rapoporte359b6a2015-10-26 09:06:06 +020072 sm750_dev->vidmem_size = ddk750_getVMSize();
Sudip Mukherjeee9363512015-03-10 14:15:35 +053073 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
Mike Rapoporte359b6a2015-10-26 09:06:06 +020074 sm750_dev->vidmem_start, sm750_dev->vidmem_size);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053075
76 /* reserve the vidmem space of smi adaptor */
Mike Rapoporte359b6a2015-10-26 09:06:06 +020077 sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
78 sm750_dev->vidmem_size);
79 if (!sm750_dev->pvMem) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +053080 pr_err("Map video memory failed\n");
81 ret = -EFAULT;
82 goto exit;
Anatoly Stepanov5e83e282015-06-29 02:44:00 +030083 } else {
Mike Rapoporte359b6a2015-10-26 09:06:06 +020084 pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
Sudip Mukherjee81dee672015-03-03 16:21:06 +053085 }
86exit:
87 return ret;
88}
89
90
91
Mike Rapoport700591a2015-10-26 09:06:01 +020092int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
Sudip Mukherjee81dee672015-03-03 16:21:06 +053093{
Greg Donaldeb0f4272015-06-18 15:06:56 -050094 struct init_status *parm;
Anatoly Stepanov29d87332015-06-29 02:43:55 +030095
Mike Rapoport1757d102015-10-26 09:05:57 +020096 parm = &sm750_dev->initParm;
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +030097 if (parm->chip_clk == 0)
Anatoly Stepanovd5fca402015-06-29 02:44:04 +030098 parm->chip_clk = (getChipType() == SM750LE) ?
Sudip Mukherjee81dee672015-03-03 16:21:06 +053099 DEFAULT_SM750LE_CHIP_CLOCK :
100 DEFAULT_SM750_CHIP_CLOCK;
101
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300102 if (parm->mem_clk == 0)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530103 parm->mem_clk = parm->chip_clk;
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300104 if (parm->master_clk == 0)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530105 parm->master_clk = parm->chip_clk/3;
106
Mike Rapoport1757d102015-10-26 09:05:57 +0200107 ddk750_initHw((initchip_param_t *)&sm750_dev->initParm);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530108 /* for sm718,open pci burst */
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200109 if (sm750_dev->devid == 0x718) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530110 POKE32(SYSTEM_CTRL,
Somya Anandd2a60372015-03-12 21:48:45 +0530111 FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530112 }
113
Anatoly Stepanov4bcdffe2015-06-29 02:43:59 +0300114 if (getChipType() != SM750LE) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530115 /* does user need CRT ?*/
Mike Rapoport1757d102015-10-26 09:05:57 +0200116 if (sm750_dev->nocrt) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530117 POKE32(MISC_CTRL,
118 FIELD_SET(PEEK32(MISC_CTRL),
119 MISC_CTRL,
Somya Anandd2a60372015-03-12 21:48:45 +0530120 DAC_POWER, OFF));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530121 /* shut off dpms */
122 POKE32(SYSTEM_CTRL,
123 FIELD_SET(PEEK32(SYSTEM_CTRL),
124 SYSTEM_CTRL,
Somya Anandd2a60372015-03-12 21:48:45 +0530125 DPMS, VNHN));
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300126 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530127 POKE32(MISC_CTRL,
128 FIELD_SET(PEEK32(MISC_CTRL),
129 MISC_CTRL,
Somya Anandd2a60372015-03-12 21:48:45 +0530130 DAC_POWER, ON));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530131 /* turn on dpms */
132 POKE32(SYSTEM_CTRL,
133 FIELD_SET(PEEK32(SYSTEM_CTRL),
134 SYSTEM_CTRL,
Somya Anandd2a60372015-03-12 21:48:45 +0530135 DPMS, VPHP));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530136 }
137
Mike Rapoport1757d102015-10-26 09:05:57 +0200138 switch (sm750_dev->pnltype) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300139 case sm750_doubleTFT:
140 case sm750_24TFT:
141 case sm750_dualTFT:
142 POKE32(PANEL_DISPLAY_CTRL,
143 FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
144 PANEL_DISPLAY_CTRL,
145 TFT_DISP,
Mike Rapoport1757d102015-10-26 09:05:57 +0200146 sm750_dev->pnltype));
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300147 break;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530148 }
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300149 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530150 /* for 750LE ,no DVI chip initilization makes Monitor no signal */
151 /* Set up GPIO for software I2C to program DVI chip in the
152 Xilinx SP605 board, in order to have video signal.
153 */
Mike Rapoportf2ea7732015-09-12 11:07:38 +0300154 sm750_sw_i2c_init(0, 1);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530155
156
Anatoly Stepanov202add22015-06-29 02:43:54 +0300157 /* Customer may NOT use CH7301 DVI chip, which has to be
158 initialized differently.
159 */
Mike Rapoport288836b2015-09-12 11:07:39 +0300160 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
Anatoly Stepanov202add22015-06-29 02:43:54 +0300161 /* The following register values for CH7301 are from
162 Chrontel app note and our experiment.
163 */
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530164 pr_info("yes,CH7301 DVI chip found\n");
Mike Rapoportd33b4202015-09-12 11:07:40 +0300165 sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
166 sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
167 sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530168 pr_info("okay,CH7301 DVI chip setup done\n");
Anatoly Stepanov202add22015-06-29 02:43:54 +0300169 }
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530170 }
171
172 /* init 2d engine */
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200173 if (!sm750_dev->accel_off)
Mike Rapoport700591a2015-10-26 09:06:01 +0200174 hw_sm750_initAccel(sm750_dev);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530175
176 return 0;
177}
178
Anatoly Stepanove188ea32015-06-29 02:43:58 +0300179int hw_sm750_output_setMode(struct lynxfb_output *output,
180 struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530181{
182 int ret;
183 disp_output_t dispSet;
184 int channel;
Anatoly Stepanov29d87332015-06-29 02:43:55 +0300185
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530186 ret = 0;
187 dispSet = 0;
188 channel = *output->channel;
189
190
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300191 if (getChipType() != SM750LE) {
192 if (channel == sm750_primary) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530193 pr_info("primary channel\n");
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300194 if (output->paths & sm750_panel)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530195 dispSet |= do_LCD1_PRI;
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300196 if (output->paths & sm750_crt)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530197 dispSet |= do_CRT_PRI;
198
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300199 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530200 pr_info("secondary channel\n");
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300201 if (output->paths & sm750_panel)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530202 dispSet |= do_LCD1_SEC;
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300203 if (output->paths & sm750_crt)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530204 dispSet |= do_CRT_SEC;
205
206 }
207 ddk750_setLogicalDispOut(dispSet);
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300208 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530209 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
210 u32 reg;
Juston Li40403c12015-07-14 21:14:48 -0700211
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530212 reg = PEEK32(DISPLAY_CONTROL_750LE);
213 reg |= 0xf;
Somya Anandd2a60372015-03-12 21:48:45 +0530214 POKE32(DISPLAY_CONTROL_750LE, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530215 }
216
Juston Lia1fe1542015-07-14 21:14:44 -0700217 pr_info("ddk setlogicdispout done\n");
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530218 return ret;
219}
220
Anatoly Stepanove188ea32015-06-29 02:43:58 +0300221int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530222{
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200223 struct sm750_dev *sm750_dev;
Mike Rapoportf11fa2a2015-10-26 09:05:59 +0200224 struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
Anatoly Stepanov29d87332015-06-29 02:43:55 +0300225
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200226 sm750_dev = par->dev;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530227
Anatoly Stepanove0ded442015-06-29 02:43:56 +0300228 switch (var->bits_per_pixel) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300229 case 8:
230 case 16:
231 break;
232 case 32:
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200233 if (sm750_dev->revid == SM750LE_REVISION_ID) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300234 pr_debug("750le do not support 32bpp\n");
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530235 return -EINVAL;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300236 }
237 break;
238 default:
239 return -EINVAL;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530240
241 }
242
243 return 0;
244}
245
246
247/*
248 set the controller's mode for @crtc charged with @var and @fix parameters
249*/
Anatoly Stepanove188ea32015-06-29 02:43:58 +0300250int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
251 struct fb_var_screeninfo *var,
252 struct fb_fix_screeninfo *fix)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530253{
Isaac Assegaibdec7772015-06-02 03:14:25 -0700254 int ret, fmt;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530255 u32 reg;
256 mode_parameter_t modparm;
257 clock_type_t clock;
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200258 struct sm750_dev *sm750_dev;
Greg Donaldeb0f4272015-06-18 15:06:56 -0500259 struct lynxfb_par *par;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530260
Anatoly Stepanov29d87332015-06-29 02:43:55 +0300261
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530262 ret = 0;
Somya Anandd2a60372015-03-12 21:48:45 +0530263 par = container_of(crtc, struct lynxfb_par, crtc);
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200264 sm750_dev = par->dev;
Mike Rapoportcfac7d62015-10-22 09:38:39 +0300265
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200266 if (!sm750_dev->accel_off) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530267 /* set 2d engine pixel format according to mode bpp */
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300268 switch (var->bits_per_pixel) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300269 case 8:
270 fmt = 0;
271 break;
272 case 16:
273 fmt = 1;
274 break;
275 case 32:
276 default:
277 fmt = 2;
278 break;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530279 }
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200280 hw_set2dformat(&sm750_dev->accel, fmt);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530281 }
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530282
283 /* set timing */
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530284 modparm.pixel_clock = ps_to_hz(var->pixclock);
285 modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
286 modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
Anatoly Stepanovd5fca402015-06-29 02:44:04 +0300287 modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530288 modparm.horizontal_display_end = var->xres;
289 modparm.horizontal_sync_width = var->hsync_len;
290 modparm.horizontal_sync_start = var->xres + var->right_margin;
291 modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
292 modparm.vertical_display_end = var->yres;
293 modparm.vertical_sync_height = var->vsync_len;
294 modparm.vertical_sync_start = var->yres + var->lower_margin;
295 modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
296
297 /* choose pll */
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300298 if (crtc->channel != sm750_secondary)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530299 clock = PRIMARY_PLL;
300 else
301 clock = SECONDARY_PLL;
302
Somya Anandd2a60372015-03-12 21:48:45 +0530303 pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
304 ret = ddk750_setModeTiming(&modparm, clock);
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300305 if (ret) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530306 pr_err("Set mode timing failed\n");
307 goto exit;
308 }
309
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300310 if (crtc->channel != sm750_secondary) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530311 /* set pitch, offset ,width,start address ,etc... */
312 POKE32(PANEL_FB_ADDRESS,
Somya Anandd2a60372015-03-12 21:48:45 +0530313 FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
314 FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)|
315 FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530316
317 reg = var->xres * (var->bits_per_pixel >> 3);
318 /* crtc->channel is not equal to par->index on numeric,be aware of that */
Mike Rapoporte3a3f9f2015-10-26 09:05:52 +0200319 reg = ALIGN(reg, crtc->line_pad);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530320
321 POKE32(PANEL_FB_WIDTH,
Somya Anandd2a60372015-03-12 21:48:45 +0530322 FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
323 FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530324
325 POKE32(PANEL_WINDOW_WIDTH,
Anatoly Stepanovd5fca402015-06-29 02:44:04 +0300326 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
Somya Anandd2a60372015-03-12 21:48:45 +0530327 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530328
329 POKE32(PANEL_WINDOW_HEIGHT,
Somya Anandd2a60372015-03-12 21:48:45 +0530330 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)|
331 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530332
Somya Anandd2a60372015-03-12 21:48:45 +0530333 POKE32(PANEL_PLANE_TL, 0);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530334
335 POKE32(PANEL_PLANE_BR,
Somya Anandd2a60372015-03-12 21:48:45 +0530336 FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)|
Isaac Assegaibdec7772015-06-02 03:14:25 -0700337 FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT, var->xres - 1));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530338
339 /* set pixel format */
340 reg = PEEK32(PANEL_DISPLAY_CTRL);
341 POKE32(PANEL_DISPLAY_CTRL,
342 FIELD_VALUE(reg,
Somya Anandd2a60372015-03-12 21:48:45 +0530343 PANEL_DISPLAY_CTRL, FORMAT,
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530344 (var->bits_per_pixel >> 4)
345 ));
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300346 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530347 /* not implemented now */
Somya Anandd2a60372015-03-12 21:48:45 +0530348 POKE32(CRT_FB_ADDRESS, crtc->oScreen);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530349 reg = var->xres * (var->bits_per_pixel >> 3);
350 /* crtc->channel is not equal to par->index on numeric,be aware of that */
Mike Rapoporte3a3f9f2015-10-26 09:05:52 +0200351 reg = ALIGN(reg, crtc->line_pad);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530352
353 POKE32(CRT_FB_WIDTH,
Somya Anandd2a60372015-03-12 21:48:45 +0530354 FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
355 FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530356
357 /* SET PIXEL FORMAT */
358 reg = PEEK32(CRT_DISPLAY_CTRL);
Somya Anandd2a60372015-03-12 21:48:45 +0530359 reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4);
360 POKE32(CRT_DISPLAY_CTRL, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530361
362 }
363
364
365exit:
366 return ret;
367}
368
Anatoly Stepanove188ea32015-06-29 02:43:58 +0300369int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
Somya Anandd2a60372015-03-12 21:48:45 +0530370 ushort red, ushort green, ushort blue)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530371{
Anatoly Stepanovd5fca402015-06-29 02:44:04 +0300372 static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
Juston Li40403c12015-07-14 21:14:48 -0700373
Somya Anandd2a60372015-03-12 21:48:45 +0530374 POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530375 return 0;
376}
377
Anatoly Stepanov14a974c2015-06-29 02:44:03 +0300378int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
379{
Isaac Assegaibdec7772015-06-02 03:14:25 -0700380 int dpms, crtdb;
Anatoly Stepanov29d87332015-06-29 02:43:55 +0300381
Anatoly Stepanov4bcdffe2015-06-29 02:43:59 +0300382 switch (blank) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300383 case FB_BLANK_UNBLANK:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300384 dpms = CRT_DISPLAY_CTRL_DPMS_0;
385 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
386 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300387 case FB_BLANK_NORMAL:
388 dpms = CRT_DISPLAY_CTRL_DPMS_0;
389 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
390 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300391 case FB_BLANK_VSYNC_SUSPEND:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300392 dpms = CRT_DISPLAY_CTRL_DPMS_2;
393 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
394 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300395 case FB_BLANK_HSYNC_SUSPEND:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300396 dpms = CRT_DISPLAY_CTRL_DPMS_1;
397 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
398 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300399 case FB_BLANK_POWERDOWN:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300400 dpms = CRT_DISPLAY_CTRL_DPMS_3;
401 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
402 break;
403 default:
404 return -EINVAL;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530405 }
406
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300407 if (output->paths & sm750_crt) {
Somya Anandd2a60372015-03-12 21:48:45 +0530408 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
409 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530410 }
411 return 0;
412}
413
Anatoly Stepanove188ea32015-06-29 02:43:58 +0300414int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530415{
Somya Anandd2a60372015-03-12 21:48:45 +0530416 unsigned int dpms, pps, crtdb;
Anatoly Stepanov29d87332015-06-29 02:43:55 +0300417
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530418 dpms = pps = crtdb = 0;
419
Anatoly Stepanov4bcdffe2015-06-29 02:43:59 +0300420 switch (blank) {
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300421 case FB_BLANK_UNBLANK:
Juston Lia1fe1542015-07-14 21:14:44 -0700422 pr_info("flag = FB_BLANK_UNBLANK\n");
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300423 dpms = SYSTEM_CTRL_DPMS_VPHP;
424 pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
425 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
426 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300427 case FB_BLANK_NORMAL:
Juston Lia1fe1542015-07-14 21:14:44 -0700428 pr_info("flag = FB_BLANK_NORMAL\n");
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300429 dpms = SYSTEM_CTRL_DPMS_VPHP;
430 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
431 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
432 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300433 case FB_BLANK_VSYNC_SUSPEND:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300434 dpms = SYSTEM_CTRL_DPMS_VNHP;
435 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
436 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
437 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300438 case FB_BLANK_HSYNC_SUSPEND:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300439 dpms = SYSTEM_CTRL_DPMS_VPHN;
440 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
441 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
442 break;
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300443 case FB_BLANK_POWERDOWN:
Anatoly Stepanov990e5662015-06-29 02:44:01 +0300444 dpms = SYSTEM_CTRL_DPMS_VNHN;
445 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
446 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
447 break;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530448 }
449
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300450 if (output->paths & sm750_crt) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530451
Isaac Assegaibdec7772015-06-02 03:14:25 -0700452 POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
453 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530454 }
455
Juston Li7b05cbe2015-07-14 21:14:47 -0700456 if (output->paths & sm750_panel)
Somya Anandd2a60372015-03-12 21:48:45 +0530457 POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530458
459 return 0;
460}
461
462
Mike Rapoport700591a2015-10-26 09:06:01 +0200463void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530464{
465 u32 reg;
Juston Li40403c12015-07-14 21:14:48 -0700466
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530467 enable2DEngine(1);
468
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300469 if (getChipType() == SM750LE) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530470 reg = PEEK32(DE_STATE1);
Isaac Assegaibdec7772015-06-02 03:14:25 -0700471 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
472 POKE32(DE_STATE1, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530473
474 reg = PEEK32(DE_STATE1);
Isaac Assegaibdec7772015-06-02 03:14:25 -0700475 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
Somya Anandd2a60372015-03-12 21:48:45 +0530476 POKE32(DE_STATE1, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530477
Anatoly Stepanov5e83e282015-06-29 02:44:00 +0300478 } else {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530479 /* engine reset */
480 reg = PEEK32(SYSTEM_CTRL);
Isaac Assegaibdec7772015-06-02 03:14:25 -0700481 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
Somya Anandd2a60372015-03-12 21:48:45 +0530482 POKE32(SYSTEM_CTRL, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530483
484 reg = PEEK32(SYSTEM_CTRL);
Isaac Assegaibdec7772015-06-02 03:14:25 -0700485 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF);
Somya Anandd2a60372015-03-12 21:48:45 +0530486 POKE32(SYSTEM_CTRL, reg);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530487 }
488
489 /* call 2d init */
Mike Rapoporte359b6a2015-10-26 09:06:06 +0200490 sm750_dev->accel.de_init(&sm750_dev->accel);
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530491}
492
Supriya Karanth6fa7db82015-03-12 01:11:00 +0900493int hw_sm750le_deWait(void)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530494{
Anatoly Stepanovd5fca402015-06-29 02:44:04 +0300495 int i = 0x10000000;
Juston Li40403c12015-07-14 21:14:48 -0700496
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300497 while (i--) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530498 unsigned int dwVal = PEEK32(DE_STATE2);
Juston Li40403c12015-07-14 21:14:48 -0700499
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300500 if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
Somya Anandd2a60372015-03-12 21:48:45 +0530501 (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) &&
Anatoly Stepanov4bcdffe2015-06-29 02:43:59 +0300502 (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530503 return 0;
504 }
505 }
506 /* timeout error */
507 return -1;
508}
509
510
Supriya Karanth6fa7db82015-03-12 01:11:00 +0900511int hw_sm750_deWait(void)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530512{
Anatoly Stepanovd5fca402015-06-29 02:44:04 +0300513 int i = 0x10000000;
Juston Li40403c12015-07-14 21:14:48 -0700514
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300515 while (i--) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530516 unsigned int dwVal = PEEK32(SYSTEM_CTRL);
Juston Li40403c12015-07-14 21:14:48 -0700517
Anatoly Stepanov6d1b3d62015-06-29 02:43:57 +0300518 if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
Isaac Assegaibdec7772015-06-02 03:14:25 -0700519 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
Anatoly Stepanov4bcdffe2015-06-29 02:43:59 +0300520 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530521 return 0;
522 }
523 }
524 /* timeout error */
525 return -1;
526}
527
528int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
Anatoly Stepanov202add22015-06-29 02:43:54 +0300529 const struct fb_var_screeninfo *var,
530 const struct fb_info *info)
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530531{
Anatoly Stepanov202add22015-06-29 02:43:54 +0300532 uint32_t total;
533 /* check params */
534 if ((var->xoffset + var->xres > var->xres_virtual) ||
535 (var->yoffset + var->yres > var->yres_virtual)) {
536 return -EINVAL;
537 }
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530538
Anatoly Stepanov202add22015-06-29 02:43:54 +0300539 total = var->yoffset * info->fix.line_length +
540 ((var->xoffset * var->bits_per_pixel) >> 3);
541 total += crtc->oScreen;
542 if (crtc->channel == sm750_primary) {
543 POKE32(PANEL_FB_ADDRESS,
544 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
545 PANEL_FB_ADDRESS, ADDRESS, total));
546 } else {
547 POKE32(CRT_FB_ADDRESS,
548 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
549 CRT_FB_ADDRESS, ADDRESS, total));
550 }
551 return 0;
Sudip Mukherjee81dee672015-03-03 16:21:06 +0530552}