static int flexfb_verify_gpios_db(struct fbtft_par *par) { int i; int num_db = buswidth; fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par->info->device, "%s()\n", __func__); if (par->gpio.dc < 0) { dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); return -EINVAL; } if (par->gpio.wr < 0) { dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n"); return -EINVAL; } if (latched && (par->gpio.latch < 0)) { dev_err(par->info->device, "Missing info about 'latch' gpio. Aborting.\n"); return -EINVAL; } if (latched) num_db=buswidth/2; for (i=0; i < num_db; i++) { if (par->gpio.db[i] < 0) { dev_err(par->info->device, "Missing info about 'db%02d' gpio. Aborting.\n", i); return -EINVAL; } } return 0; }
static int set_gamma(struct fbtft_par *par, unsigned long *curves) { unsigned long mask[] = { 0b11111, 0b11111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, \ 0b11111, 0b11111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b111 }; int i,j; fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); /* apply mask */ for (i=0;i<2;i++) for (j=0;j<10;j++) CURVE(i,j) &= mask[i*par->gamma.num_values + j]; write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4) ); write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6) ); write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8) ); write_reg(par, 0x0035, CURVE(0, 3) << 8 | CURVE(0, 2) ); write_reg(par, 0x0036, CURVE(0, 1) << 8 | CURVE(0, 0) ); write_reg(par, 0x0037, CURVE(1, 5) << 8 | CURVE(1, 4) ); write_reg(par, 0x0038, CURVE(1, 7) << 8 | CURVE(1, 6) ); write_reg(par, 0x0039, CURVE(1, 9) << 8 | CURVE(1, 8) ); write_reg(par, 0x003C, CURVE(1, 3) << 8 | CURVE(1, 2) ); write_reg(par, 0x003D, CURVE(1, 1) << 8 | CURVE(1, 0) ); return 0; }
/* ili9320, ili9325 */ static void flexfb_set_addr_win_1(struct fbtft_par *par, int xs, int ys, int xe, int ye) { fbtft_dev_dbg(DEBUG_SET_ADDR_WIN, par->info->device, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); switch (par->info->var.rotate) { /* R20h = Horizontal GRAM Start Address */ /* R21h = Vertical GRAM Start Address */ case 0: write_reg(par, 0x0020, xs); write_reg(par, 0x0021, ys); break; case 2: write_reg(par, 0x0020, width - 1 - xs); write_reg(par, 0x0021, height - 1 - ys); break; case 1: write_reg(par, 0x0020, width - 1 - ys); write_reg(par, 0x0021, xs); break; case 3: write_reg(par, 0x0020, ys); write_reg(par, 0x0021, height - 1 - xs); break; } write_reg(par, 0x0022); /* Write Data to GRAM */ }
/* ssd1289 */ static void flexfb_set_addr_win_2(struct fbtft_par *par, int xs, int ys, int xe, int ye) { fbtft_dev_dbg(DEBUG_SET_ADDR_WIN, par->info->device, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); switch (par->info->var.rotate) { /* R4Eh - Set GDDRAM X address counter */ /* R4Fh - Set GDDRAM Y address counter */ case 0: write_reg(par, 0x4e, xs); write_reg(par, 0x4f, ys); break; case 2: write_reg(par, 0x4e, par->info->var.xres - 1 - xs); write_reg(par, 0x4f, par->info->var.yres - 1 - ys); break; case 1: write_reg(par, 0x4e, par->info->var.yres - 1 - ys); write_reg(par, 0x4f, xs); break; case 3: write_reg(par, 0x4e, ys); write_reg(par, 0x4f, par->info->var.xres - 1 - xs); break; } /* R22h - RAM data write */ write_reg(par, 0x22, 0); }
void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) { struct fbtft_par *par = info->par; unsigned dirty_lines_start, dirty_lines_end; struct page *page; unsigned long index; unsigned y_low = 0, y_high = 0; int count = 0; spin_lock(&par->dirty_lock); dirty_lines_start = par->dirty_lines_start; dirty_lines_end = par->dirty_lines_end; /* set display line markers as clean */ par->dirty_lines_start = par->info->var.yres - 1; par->dirty_lines_end = 0; spin_unlock(&par->dirty_lock); /* Mark display lines as dirty */ list_for_each_entry(page, pagelist, lru) { count++; index = page->index << PAGE_SHIFT; y_low = index / info->fix.line_length; y_high = (index + PAGE_SIZE - 1) / info->fix.line_length; fbtft_dev_dbg(DEBUG_DEFERRED_IO, par, info->device, "page->index=%lu y_low=%d y_high=%d\n", page->index, y_low, y_high); if (y_high > info->var.yres - 1) y_high = info->var.yres - 1; if (y_low < dirty_lines_start) dirty_lines_start = y_low; if (y_high > dirty_lines_end) dirty_lines_end = y_high; }
static int sainsmart18fb_probe(struct spi_device *spi) { struct fb_info *info; struct fbtft_par *par; int ret; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); info = fbtft_framebuffer_alloc(&sainsmart18_display, &spi->dev); if (!info) return -ENOMEM; par = info->par; par->spi = spi; fbtft_debug_init(par); par->fbtftops.init_display = sainsmart18fb_init_display; par->fbtftops.verify_gpios = sainsmart18fb_verify_gpios; par->fbtftops.register_backlight = fbtft_register_backlight; ret = fbtft_register_framebuffer(info); if (ret < 0) goto out_release; return 0; out_release: fbtft_framebuffer_release(info); return ret; }
static int ssd1351fb_probe(struct spi_device *spi) { struct fb_info *info; struct fbtft_par *par; int ret; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); info = fbtft_framebuffer_alloc(&ssd1351fb_display, &spi->dev); if (!info) return -ENOMEM; par = info->par; par->spi = spi; fbtft_debug_init(par); par->fbtftops.init_display = ssd1351fb_init_display; par->fbtftops.set_addr_win = ssd1351fb_set_addr_win; par->fbtftops.verify_gpios = ssd1351fb_verify_gpios; par->fbtftops.blank = blank; par->fbtftops.set_gamma = set_gamma; ret = fbtft_register_framebuffer(info); if (ret >= 0) return 0; fbtft_framebuffer_release(info); return ret; }
void ili9341fb_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { uint8_t xsl, xsh, xel, xeh, ysl, ysh, yel, yeh; u16 *p = (u16 *)par->buf; int i = 0; fbtft_dev_dbg(DEBUG_SET_ADDR_WIN, par->info->device, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); xsl = (uint8_t)(xs & 0xff); xsh = (uint8_t)((xs >> 8) & 0xff); xel = (uint8_t)(xe & 0xff); xeh = (uint8_t)((xe >> 8) & 0xff); ysl = (uint8_t)(ys & 0xff); ysh = (uint8_t)((ys >> 8) & 0xff); yel = (uint8_t)(ye & 0xff); yeh = (uint8_t)((ye >> 8) & 0xff); write_cmd(par, FBTFT_CASET); write_data(par, xsh); write_data(par, xsl); write_data(par, xeh); write_data(par, xel); write_cmd(par, FBTFT_RASET); write_data(par, ysh); write_data(par, ysl); write_data(par, yeh); write_data(par, yel); write_cmd(par, FBTFT_RAMWR); write_flush(par); }
/* Grayscale Lookup Table GS1 - GS63 The "Gamma curve" contains the relative values between the entries in the Lookup table. From datasheet: The next 63 data bytes define Gray Scale (GS) Table by setting the gray scale pulse width in unit of DCLK's (ranges from 0d ~ 180d) 0 = Setting of GS1 < Setting of GS2 < Setting of GS3..... < Setting of GS62 < Setting of GS63 */ static int set_gamma(struct fbtft_par *par, unsigned long *curves) { int i, acc = 0; fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); /* verify lookup table */ for (i=0;i<63;i++) { acc += curves[i]; if (acc > 180) { dev_err(par->info->device, "Illegal value(s) in Grayscale Lookup Table. At index=%d, the accumulated value has exceeded 180\n", i); return -EINVAL; } if (curves[i] == 0) { dev_err(par->info->device, "Illegal value in Grayscale Lookup Table. Value can't be zero\n"); return -EINVAL; } } acc = 0; write_cmd(par, 0xB8); for (i=0;i<63;i++) { acc += curves[i]; write_data(par, acc); } return 0; }
static int itdb28fb_remove_pdev(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &pdev->dev, "%s()\n", __func__); return itdb28fb_remove_common(&pdev->dev, info); }
static int itdb28fb_remove_spi(struct spi_device *spi) { struct fb_info *info = spi_get_drvdata(spi); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); return itdb28fb_remove_common(&spi->dev, info); }
static int itdb28fb_verify_gpios(struct fbtft_par *par) { int i; fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par->info->device, "%s()\n", __func__); if (par->gpio.dc < 0) { dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); return -EINVAL; } if (par->pdev) { if (par->gpio.wr < 0) { dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n"); return -EINVAL; } for (i=0;i < 8;i++) { if (par->gpio.db[i] < 0) { dev_err(par->info->device, "Missing info about 'db%02d' gpio. Aborting.\n", i); return -EINVAL; } } } return 0; }
static int blank(struct fbtft_par *par, bool on) { fbtft_dev_dbg(DEBUG_BLANK, par->info->device, "%s(blank=%s)\n", __func__, on ? "true" : "false"); if (on) write_cmd(par, 0xAE); else write_cmd(par, 0xAF); return 0; }
static int nokia3310fb_init_display(struct fbtft_par *par) { u8 contrast = 0x40; /* between 0x00 and 0x7F */ u8 tc = 0; /* Temperature coefficient, between 0 and 3 */ u8 bias = 4; /* Bias, between 0 and 7 */ fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); par->fbtftops.reset(par); /* Function set */ write_reg(par, 0x21); /* 5:1 1 2:0 PD - Powerdown control: chip is active 1:0 V - Entry mode: horizontal addressing 0:1 H - Extended instruction set control: extended */ /* H=1 Set Vop (contrast) */ write_reg(par, 0x80 | contrast); /* 7:1 1 6-0: Vop[6:0] - Operation voltage */ /* H=1 Temperature control */ write_reg(par, 0x04 | tc); /* 2:1 1 1:x TC1 - Temperature Coefficient: 0x10 0:x TC0 */ /* H=1 Bias system */ write_reg(par, 0x10 | bias); /* 4:1 1 3:0 0 2:x BS2 - Bias System 1:x BS1 0:x BS0 */ /* Function set */ write_reg(par, 0x22); /* 5:1 1 2:0 PD - Powerdown control: chip is active 1:1 V - Entry mode: vertical addressing 0:0 H - Extended instruction set control: basic */ /* H=0 Display control */ write_reg(par, 0x08 | 4); /* 3:1 1 2:1 D - DE: 10=normal mode 1:0 0 0:0 E */ return 0; }
static int nokia3310fb_verify_gpios(struct fbtft_par *par) { fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par->info->device, "%s()\n", __func__); if (par->gpio.dc < 0) { dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); return -EINVAL; } return 0; }
static int ili9341fb_probe(struct spi_device *spi) { struct fb_info *info; struct fbtft_par *par; int ret; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); info = fbtft_framebuffer_alloc(&ili9341fb_display, &spi->dev); if (!info) return -ENOMEM; par = info->par; par->spi = spi; fbtft_debug_init(par); par->fbtftops.init_display = ili9341fb_init_display; par->fbtftops.register_backlight = fbtft_register_backlight; par->fbtftops.request_gpios_match = ili9341fb_request_gpios_match; par->fbtftops.write_data_command = fbtft_write_data_command8_bus9; par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; par->fbtftops.set_addr_win = ili9341fb_set_addr_win; spi->bits_per_word=9; ret = spi->master->setup(spi); if (ret) { dev_warn(&spi->dev, "9-bit SPI not available, emulating using 8-bit.\n"); spi->bits_per_word=8; ret = spi->master->setup(spi); if (ret) goto fbreg_fail; /* allocate buffer with room for dc bits */ par->extra = vzalloc(par->txbuf.len + (par->txbuf.len / 8)); if (!par->extra) { ret = -ENOMEM; goto fbreg_fail; } par->fbtftops.write = ili9341fb_write_emulate_9bit; } ret = fbtft_register_framebuffer(info); if (ret < 0) goto fbreg_fail; return 0; fbreg_fail: if (par->extra) vfree(par->extra); fbtft_framebuffer_release(info); return ret; }
static int flexfb_remove_common(struct device *dev, struct fb_info *info) { fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s()\n", __func__); if (info) { fbtft_unregister_framebuffer(info); fbtft_framebuffer_release(info); } return 0; }
static int sainsmart18fb_remove(struct spi_device *spi) { struct fb_info *info = spi_get_drvdata(spi); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); if (info) { fbtft_unregister_framebuffer(info); fbtft_framebuffer_release(info); } return 0; }
static int itdb28fb_remove_common(struct device *dev, struct fb_info *info) { fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s()\n", __func__); if (info) { fbtft_unregister_framebuffer(info); fbtft_framebuffer_release(info); } sysfs_remove_group(&dev->kobj, &itdb28fb_attr_group); return 0; }
static int itdb28fb_probe_common(struct spi_device *sdev, struct platform_device *pdev) { struct device *dev; struct fb_info *info; struct fbtft_par *par; int ret; if (sdev) dev = &sdev->dev; else dev = &pdev->dev; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s()\n", __func__); info = fbtft_framebuffer_alloc(&itdb28fb_display, dev); if (!info) return -ENOMEM; par = info->par; if (sdev) par->spi = sdev; else par->pdev = pdev; fbtft_debug_init(par); par->fbtftops.init_display = itdb28fb_init_display; par->fbtftops.set_gamma = set_gamma; par->fbtftops.register_backlight = fbtft_register_backlight; par->fbtftops.write_reg = fbtft_write_reg16_bus8; par->fbtftops.set_addr_win = itdb28fb_set_addr_win; par->fbtftops.verify_gpios = itdb28fb_verify_gpios; if (pdev) par->fbtftops.write = fbtft_write_gpio8_wr; ret = fbtft_register_framebuffer(info); if (ret < 0) goto out_release; ret = sysfs_create_group(&pdev->dev.kobj, &itdb28fb_attr_group); if (ret) goto out_release; dev_set_drvdata(&pdev->dev, par); return 0; out_release: fbtft_framebuffer_release(info); return ret; }
static int nokia3310fb_probe(struct spi_device *spi) { struct fb_info *info; struct fbtft_par *par; int ret; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); if (rotate) { nokia3310fb_display.width = HEIGHT; nokia3310fb_display.height = WIDTH; } else { nokia3310fb_display.width = WIDTH; nokia3310fb_display.height = HEIGHT; } info = fbtft_framebuffer_alloc(&nokia3310fb_display, &spi->dev); if (!info) return -ENOMEM; info->fix.visual = FB_VISUAL_MONO10; info->var.red.offset = 0; info->var.red.length = 0; info->var.green.offset = 0; info->var.green.length = 0; info->var.blue.offset = 0; info->var.blue.length = 0; par = info->par; par->spi = spi; fbtft_debug_init(par); par->fbtftops.write_data_command = fbtft_write_data_command8_bus8; par->fbtftops.verify_gpios = nokia3310fb_verify_gpios; par->fbtftops.init_display = nokia3310fb_init_display; par->fbtftops.register_backlight = fbtft_register_backlight; par->fbtftops.update_display = nokia3310fb_update_display; ret = fbtft_register_framebuffer(info); if (ret < 0) goto out_release; return 0; out_release: fbtft_framebuffer_release(info); return ret; }
static int ili9341fb_remove(struct spi_device *spi) { struct fb_info *info = spi_get_drvdata(spi); struct fbtft_par *par; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); if (info) { fbtft_unregister_framebuffer(info); par = info->par; if (par->extra) vfree(par->extra); fbtft_framebuffer_release(info); } return 0; }
static int nokia3310fb_remove(struct spi_device *spi) { struct fb_info *info = spi_get_drvdata(spi); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__); if (info) { if (info->bl_dev) { /* turn off backlight or else it will fade out */ info->bl_dev->props.power = FB_BLANK_POWERDOWN; info->bl_dev->ops->update_status(info->bl_dev); } fbtft_unregister_framebuffer(info); fbtft_framebuffer_release(info); } return 0; }
void nokia3310fb_update_display(struct fbtft_par *par) { u8 *vmem8 = vmem8 = par->info->screen_base; u8 *buf = par->txbuf.buf; int i; int ret = 0; fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par->info->device, "%s()\n", __func__); if (par->info->var.xres == WIDTH) { /* rearrange */ for (i=0; i<84; i++) { buf[i*6+0] = vmem8[i*6+5]; buf[i*6+1] = vmem8[i*6+4]; buf[i*6+2] = vmem8[i*6+3]; buf[i*6+3] = vmem8[i*6+2]; buf[i*6+4] = vmem8[i*6+1]; buf[i*6+5] = vmem8[i*6+0]; } } else { /* rearrange and rotate */ dev_err(par->info->device, "%s: rotation not supported yet\n", __func__); return; } /* H=0 Set X address of RAM */ write_reg(par, 0x80); /* 7:1 1 6-0: X[6:0] - 0x00 */ /* H=0 Set Y address of RAM */ write_reg(par, 0x40); /* 7:0 0 6:1 1 2-0: Y[2:0] - 0x0 */ /* Write data */ gpio_set_value(par->gpio.dc, 1); ret = par->fbtftops.write(par, buf, par->info->fix.smem_len); if (ret < 0) dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret); }
void adafruit22fb_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { u16 *p = (u16 *)par->buf; int i = 0; fbtft_dev_dbg(DEBUG_SET_ADDR_WIN, par->info->device, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); write_cmd(par, FBTFT_CASET); write_data(par, 0x00); write_data(par, xs); write_data(par, 0x00); write_data(par, xe); write_cmd(par, FBTFT_RASET); write_data(par, 0x00); write_data(par, ys); write_data(par, 0x00); write_data(par, ye); write_cmd(par, FBTFT_RAMWR); write_flush(par); }
static int flexfb_probe_common(struct spi_device *sdev, struct platform_device *pdev) { struct device *dev; struct fb_info *info; struct fbtft_par *par; int ret; initp = init; initp_num = init_num; if (sdev) dev = &sdev->dev; else dev = &pdev->dev; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s(%s)\n", __func__, sdev ? "'SPI device'" : "'Platform device'"); if (chip) { if (!strcmp(chip, "st7735r")) { if (!width) width = 128; if (!height) height = 160; if (init_num == 0) { initp = st7735r_init; initp_num = ARRAY_SIZE(st7735r_init); } } else if (!strcmp(chip, "hx8340bn")) { if (!width) width = 176; if (!height) height = 220; setaddrwin = 0; if (init_num == 0) { initp = hx8340bn_init; initp_num = ARRAY_SIZE(hx8340bn_init); } } else if (!strcmp(chip, "ili9225")) { if (!width) width = 176; if (!height) height = 220; setaddrwin = 0; regwidth = 16; if (init_num == 0) { initp = ili9225_init; initp_num = ARRAY_SIZE(ili9225_init); } } else if (!strcmp(chip, "ili9320")) { if (!width) width = 240; if (!height) height = 320; setaddrwin = 1; regwidth = 16; if (init_num == 0) { initp = ili9320_init; initp_num = ARRAY_SIZE(ili9320_init); } } else if (!strcmp(chip, "ili9325")) { if (!width) width = 240; if (!height) height = 320; setaddrwin = 1; regwidth = 16; if (init_num == 0) { initp = ili9325_init; initp_num = ARRAY_SIZE(ili9325_init); } } else if (!strcmp(chip, "ili9341")) { if (!width) width = 240; if (!height) height = 320; setaddrwin = 0; regwidth = 8; if (init_num == 0) { initp = ili9341_init; initp_num = ARRAY_SIZE(ili9341_init); } } else if (!strcmp(chip, "ssd1289")) { if (!width) width = 240; if (!height) height = 320; setaddrwin = 2; regwidth = 16; if (init_num == 0) { initp = ssd1289_init; initp_num = ARRAY_SIZE(ssd1289_init); } } else if (!strcmp(chip, "ssd1351")) { if (!width) width = 128; if (!height) height = 128; setaddrwin = 3; if (init_num == 0) { initp = ssd1351_init; initp_num = ARRAY_SIZE(ssd1351_init); } } else { dev_err(dev, "chip=%s is not supported\n", chip); return -EINVAL; } } if (width == 0 || height == 0) { dev_err(dev, "argument(s) missing: width and height has to be set.\n"); return -EINVAL; } flex_display.width = width; flex_display.height = height; fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "Display resolution: %dx%d\n", width, height); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "chip = %s\n", chip ? chip : "not set"); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "setaddrwin = %d\n", setaddrwin); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "regwidth = %d\n", regwidth); fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "buswidth = %d\n", buswidth); info = fbtft_framebuffer_alloc(&flex_display, dev); if (!info) return -ENOMEM; par = info->par; if (sdev) par->spi = sdev; else par->pdev = pdev; fbtft_debug_init(par); par->fbtftops.init_display = flexfb_init_display; /* registerwrite functions */ switch (regwidth) { case 8: par->fbtftops.write_reg = fbtft_write_reg8_bus8; par->fbtftops.write_data_command = fbtft_write_data_command8_bus8; break; case 16: par->fbtftops.write_reg = fbtft_write_reg16_bus8; par->fbtftops.write_data_command = fbtft_write_data_command16_bus8; break; default: dev_err(dev, "argument 'regwidth': %d is not supported.\n", regwidth); return -EINVAL; } /* bus functions */ if (sdev) { switch (buswidth) { case 8: par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; if (!par->startbyte) par->fbtftops.verify_gpios = flexfb_verify_gpios_dc; break; case 9: if (regwidth == 16) { dev_err(dev, "argument 'regwidth': %d is not supported with buswidth=%d and SPI.\n", regwidth, buswidth); return -EINVAL; } par->fbtftops.write_data_command = fbtft_write_data_command8_bus9; par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; sdev->bits_per_word=9; ret = sdev->master->setup(sdev); if (ret) { dev_err(dev, "SPI 9-bit setup failed: %d.\n", ret); return ret; } break; default: dev_err(dev, "argument 'buswidth': %d is not supported with SPI.\n", buswidth); return -EINVAL; } par->fbtftops.write = fbtft_write_spi; } else { par->fbtftops.verify_gpios = flexfb_verify_gpios_db; switch (buswidth) { case 8: par->fbtftops.write = fbtft_write_gpio8_wr; par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; break; case 16: par->fbtftops.write_reg = fbtft_write_reg16_bus16; par->fbtftops.write_data_command = fbtft_write_data_command16_bus16; if (latched) par->fbtftops.write = fbtft_write_gpio16_wr_latched; else par->fbtftops.write = fbtft_write_gpio16_wr; par->fbtftops.write_vmem = fbtft_write_vmem16_bus16; break; default: dev_err(dev, "argument 'buswidth': %d is not supported with parallel.\n", buswidth); return -EINVAL; } } /* set_addr_win function */ switch (setaddrwin) { case 0: /* use default */ break; case 1: par->fbtftops.set_addr_win = flexfb_set_addr_win_1; break; case 2: par->fbtftops.set_addr_win = flexfb_set_addr_win_2; break; case 3: par->fbtftops.set_addr_win = set_addr_win_3; break; default: dev_err(dev, "argument 'setaddrwin': unknown value %d.\n", setaddrwin); return -EINVAL; } if (!nobacklight) par->fbtftops.register_backlight = fbtft_register_backlight; ret = fbtft_register_framebuffer(info); if (ret < 0) goto out_release; return 0; out_release: fbtft_framebuffer_release(info); return ret; }
static int sainsmart18fb_init_display(struct fbtft_par *par) { fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); par->fbtftops.reset(par); /* SWRESET - Software reset */ write_reg(par, 0x01); mdelay(150); /* SLPOUT - Sleep out & booster on */ write_reg(par, 0x11); mdelay(500); /* FRMCTR1 - frame rate control - normal mode */ write_reg(par, 0xB1, 0x01, 0x2C, 0x2D); /* frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ /* FRMCTR2 - frame rate control - idle mode */ write_reg(par, 0xB2, 0x01, 0x2C, 0x2D); /* frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ /* FRMCTR1 - frame rate control - partial mode */ write_reg(par, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D); /* dot inversion mode, line inversion mode */ /* INVCTR - // display inversion control */ write_reg(par, 0xB4, 0x07); /* no inversion */ /* PWCTR1 - Power Control */ write_reg(par, 0xC0, 0xA2, 0x02, 0x84); /* -4.6V, AUTO mode */ /* PWCTR2 - Power Control */ write_reg(par, 0xC1, 0xC5); /* VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */ /* PWCTR3 - Power Control */ write_reg(par, 0xC2, 0x0A, 0x00); /* Opamp current small, Boost frequency */ /* PWCTR4 - Power Control */ write_reg(par, 0xC3, 0x8A, 0x2A); /* BCLK/2, Opamp current small & Medium low */ /* PWCTR5 - Power Control */ write_reg(par, 0xC4, 0x8A, 0xEE); /* VMCTR1 - Power Control */ write_reg(par, 0xC5, 0x0E); /* INVOFF - Display inversion off */ write_reg(par, 0x20); /* MADCTL - Memory data access control */ /* Mode selection pin SRGB: RGB direction select H/W pin for color filter setting: 0=RGB, 1=BGR */ /* MADCTL RGB bit: RGB-BGR ORDER: 0=RGB color filter panel, 1=BGR color filter panel */ #define MY (1 << 7) #define MX (1 << 6) #define MV (1 << 5) switch (par->info->var.rotate) { case 0: write_reg(par, 0x36, MX | MY | (par->bgr << 3)); break; case 1: write_reg(par, 0x36, MY | MV | (par->bgr << 3)); break; case 2: write_reg(par, 0x36, (par->bgr << 3)); break; case 3: write_reg(par, 0x36, MX | MV | (par->bgr << 3)); break; } /* COLMOD - Interface pixel format */ write_reg(par, 0x3A, 0x05); /* GMCTRP1 - Gamma control */ write_reg(par, 0xE0, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10); /* write_reg(par, 0xE0, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10); */ /* GMCTRN1 - Gamma control */ write_reg(par, 0xE1, 0x0f , 0x1b , 0x0f , 0x17 , 0x33 , 0x2c , 0x29 , 0x2e , 0x30 , 0x30 , 0x39 , 0x3f , 0x00 , 0x07 , 0x03 , 0x10); /* write_reg(par, 0xE1, 0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10); */ /* DISPON - Display On */ write_reg(par, 0x29); mdelay(100); /* NORON - Partial off (Normal) */ write_reg(par, 0x13); mdelay(10); return 0; }
static int ssd1351fb_init_display(struct fbtft_par *par) { fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); // Reset the device. par->fbtftops.reset(par); // Write the init sequence. write_cmd(par, 0xfd); // Command Lock write_data(par, 0x12); write_cmd(par, 0xfd); // Command Lock write_data(par, 0xb1); write_cmd(par, 0xae); // Display Off write_cmd(par, 0xb3); // Front Clock Div write_data(par, 0xf1); write_cmd(par, 0xca); // Set Mux Ratio write_data(par, 0x7f); write_cmd(par, 0xa0); // Set Colour Depth write_data(par, 0x74); // 0xb4 write_cmd(par, 0x15); // Set Column Address write_data(par, 0x00); write_data(par, 0x7f); write_cmd(par, 0x75); // Set Row Address write_data(par, 0x00); write_data(par, 0x7f); write_cmd(par, 0xa1); // Set Display Start Line write_data(par, 0x00); write_cmd(par, 0xa2); // Set Display Offset write_data(par, 0x00); write_cmd(par, 0xb5); // Set GPIO write_data(par, 0x00); write_cmd(par, 0xab); // Set Function Selection write_data(par, 0x01); write_cmd(par, 0xb1); // Set Phase Length write_data(par, 0x32); write_cmd(par, 0xb4); // Set Segment Low Voltage write_data(par, 0xa0); write_data(par, 0xb5); write_data(par, 0x55); write_cmd(par, 0xbb); // Set Precharge Voltage write_data(par, 0x17); write_cmd(par, 0xbe); // Set VComH Voltage write_data(par, 0x05); write_cmd(par, 0xc1); // Set Contrast write_data(par, 0xc8); write_data(par, 0x80); write_data(par, 0xc8); write_cmd(par, 0xc7); // Set Master Contrast write_data(par, 0x0f); write_cmd(par, 0xb6); // Set Second Precharge Period write_data(par, 0x01); write_cmd(par, 0xa6); // Set Display Mode Reset write_cmd(par, 0xaf); // Set Sleep Mode Display On return 0; }
static int flexfb_init_display(struct fbtft_par *par) { char msg[128]; char str[16]; int i = 0; int j; fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); par->fbtftops.reset(par); if (par->gpio.cs != -1) gpio_set_value(par->gpio.cs, 0); /* Activate chip */ /* make sure stop marker exists */ if (initp[initp_num - 1] != -3) { dev_err(par->info->device, "argument 'init': missing stop marker (-3) at end of init sequence\n"); return -1; } while (i < initp_num) { if (initp[i] >= 0) { dev_err(par->info->device, "argument 'init': missing delimiter at position %d\n", i); return -1; } if (initp[i] == -3) { /* done */ return 0; } if ( ((i+1) == initp_num) || (initp[i+1] < 0) ) { dev_err(par->info->device, "argument 'init': missing value after delimiter %d at position %d\n", initp[i], i); return -1; } switch (initp[i]) { case -1: i++; /* make debug message */ strcpy(msg, ""); j = i + 1; while (initp[j] >= 0) { sprintf(str, "0x%02X ", initp[j]); strcat(msg, str); j++; } fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "init: write(0x%02X) %s\n", initp[i], msg); /* Write */ par->fbtftops.write_data_command(par, 0, initp[i++]); while (initp[i] >= 0) { par->fbtftops.write_data_command(par, 1, initp[i++]); } break; case -2: i++; fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "init: mdelay(%d)\n", initp[i]); mdelay(initp[i++]); break; default: dev_err(par->info->device, "argument 'init': unknown delimiter %d at position %d\n", initp[i], i); return -1; } } dev_err(par->info->device, "%s: something is wrong. Shouldn't get here.\n", __func__); return -1; }
static int ili9341fb_init_display(struct fbtft_par *par) { u16 *p = (u16 *)par->buf; int i = 0; fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__); par->fbtftops.reset(par); /* startup sequence for Watterott's MI0283QT9 */ #if 0 // not needed write_cmd(par, LCD_CMD_RESET); write_flush(par); mdelay(120); #endif write_cmd(par, LCD_CMD_DISPLAY_OFF); write_flush(par); mdelay(20); //send init commands write_cmd(par, LCD_CMD_POWER_CTRLB); write_data(par, 0x00); write_data(par, 0x83); //83 81 AA write_data(par, 0x30); write_cmd(par, LCD_CMD_POWERON_SEQ_CTRL); write_data(par, 0x64); //64 67 write_data(par, 0x03); write_data(par, 0x12); write_data(par, 0x81); write_cmd(par, LCD_CMD_DRV_TIMING_CTRLA); write_data(par, 0x85); write_data(par, 0x01); write_data(par, 0x79); //79 78 write_cmd(par, LCD_CMD_POWER_CTRLA); write_data(par, 0x39); write_data(par, 0X2C); write_data(par, 0x00); write_data(par, 0x34); write_data(par, 0x02); write_cmd(par, LCD_CMD_PUMP_RATIO_CTRL); write_data(par, 0x20); write_cmd(par, LCD_CMD_DRV_TIMING_CTRLB); write_data(par, 0x00); write_data(par, 0x00); write_cmd(par, LCD_CMD_POWER_CTRL1); write_data(par, 0x26); //26 25 write_cmd(par, LCD_CMD_POWER_CTRL2); write_data(par, 0x11); write_cmd(par, LCD_CMD_VCOM_CTRL1); write_data(par, 0x35); write_data(par, 0x3E); write_cmd(par, LCD_CMD_VCOM_CTRL2); write_data(par, 0xBE); //BE 94 write_cmd(par, LCD_CMD_FRAME_CTRL); write_data(par, 0x00); write_data(par, 0x1B); //1B 70 write_cmd(par, LCD_CMD_DISPLAY_CTRL); write_data(par, 0x0A); write_data(par, 0x82); write_data(par, 0x27); write_data(par, 0x00); write_cmd(par, LCD_CMD_ENTRY_MODE); write_data(par, 0x07); write_cmd(par, LCD_CMD_PIXEL_FORMAT); write_data(par, 0x55); //16bit // orientation write_cmd(par, LCD_CMD_MEMACCESS_CTRL); switch (par->info->var.rotate) { case 0: write_data(par, (1<<MEM_X) | (!par->bgr << MEM_BGR)); break; case 1: write_data(par, (1<<MEM_V) | (1<<MEM_L) | (!par->bgr << MEM_BGR)); break; case 2: write_data(par, (1<<MEM_Y) | (!par->bgr << MEM_BGR)); break; case 3: write_data(par, (1<<MEM_Y) | (1<<MEM_X)| (1<<MEM_V) | (!par->bgr << MEM_BGR)); break; } write_cmd(par, LCD_CMD_SLEEPOUT); write_flush(par); mdelay(120); write_cmd(par, LCD_CMD_DISPLAY_ON); write_flush(par); mdelay(20); return 0; }