^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2008, Jaya Kumar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This driver is written to be used with the Broadsheet display controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * It is intended to be architecture independent. A board specific driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * must be used to perform all the physical IO interactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <video/broadsheetfb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* track panel specific parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct panel_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u16 sdcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u16 gdcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u16 lutfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u16 fsynclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u16 fendfbegin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u16 lsynclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u16 lendlbegin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u16 pixclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* table of panel specific parameters to be indexed into by the board drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static struct panel_info panel_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { /* standard 6" on TFT backplane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .w = 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .h = 600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .sdcfg = (100 | (1 << 8) | (1 << 9)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .gdcfg = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .lutfmt = (4 | (1 << 7)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .fsynclen = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .fendfbegin = (10 << 8) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .lsynclen = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .lendlbegin = (100 << 8) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .pixclk = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { /* custom 3.7" flexible on PET or steel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .w = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .h = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .gdcfg = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .lutfmt = (4 | (1 << 7)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .fsynclen = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .fendfbegin = (80 << 8) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .lsynclen = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .lendlbegin = (80 << 8) | 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .pixclk = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { /* standard 9.7" on TFT backplane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .w = 1200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .h = 825,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .gdcfg = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .lutfmt = (4 | (1 << 7)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .fsynclen = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .fendfbegin = (4 << 8) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .lsynclen = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .lendlbegin = (60 << 8) | 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .pixclk = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define DPY_W 800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DPY_H 600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static struct fb_fix_screeninfo broadsheetfb_fix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .id = "broadsheetfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .type = FB_TYPE_PACKED_PIXELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .visual = FB_VISUAL_STATIC_PSEUDOCOLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .xpanstep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .ypanstep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .ywrapstep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .line_length = DPY_W,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .accel = FB_ACCEL_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct fb_var_screeninfo broadsheetfb_var = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .xres = DPY_W,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .yres = DPY_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .xres_virtual = DPY_W,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .yres_virtual = DPY_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .bits_per_pixel = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .grayscale = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .red = { 0, 4, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .green = { 0, 4, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .blue = { 0, 4, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .transp = { 0, 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* main broadsheetfb functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) par->board->set_ctl(par, BS_WR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) par->board->set_hdb(par, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) par->board->set_ctl(par, BS_WR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) par->board->set_ctl(par, BS_DC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) broadsheet_gpio_issue_data(par, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) par->board->set_ctl(par, BS_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) broadsheet_gpio_issue_cmd(par, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) par->board->set_ctl(par, BS_DC, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) par->board->set_ctl(par, BS_CS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int argc, u16 *argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) par->board->set_ctl(par, BS_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) broadsheet_gpio_issue_cmd(par, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) par->board->set_ctl(par, BS_DC, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) for (i = 0; i < argc; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) broadsheet_gpio_issue_data(par, argv[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) par->board->set_ctl(par, BS_CS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int argc, u16 *argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) par->board->mmio_write(par, BS_MMIO_CMD, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i < argc; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (par->board->mmio_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) par->board->mmio_write(par, BS_MMIO_CMD, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) broadsheet_gpio_send_command(par, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int argc, u16 *argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (par->board->mmio_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u16 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) par->board->set_ctl(par, BS_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) par->board->set_ctl(par, BS_DC, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) par->board->set_ctl(par, BS_WR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) tmp = (data[i] & 0x0F) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tmp |= (data[i] & 0x0F00) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) par->board->set_hdb(par, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) par->board->set_ctl(par, BS_WR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) par->board->set_ctl(par, BS_CS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u16 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) tmp = (data[i] & 0x0F) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) tmp |= (data[i] & 0x0F00) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) par->board->mmio_write(par, BS_MMIO_DATA, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u16 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (par->board->mmio_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) broadsheet_mmio_burst_write(par, size, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) broadsheet_gpio_burst_write(par, size, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u16 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* wait for ready to go hi. (lo is busy) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* cs lo, dc lo for cmd, we lo for each data, db as usual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) par->board->set_ctl(par, BS_DC, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) par->board->set_ctl(par, BS_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) par->board->set_ctl(par, BS_WR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) res = par->board->get_hdb(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* strobe wr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) par->board->set_ctl(par, BS_WR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) par->board->set_ctl(par, BS_CS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static u16 broadsheet_get_data(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (par->board->mmio_read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return par->board->mmio_read(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return broadsheet_gpio_get_data(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* wait for ready to go hi. (lo is busy) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* cs lo, dc lo for cmd, we lo for each data, db as usual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) par->board->set_ctl(par, BS_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) par->board->set_ctl(par, BS_DC, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) broadsheet_gpio_issue_data(par, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) broadsheet_gpio_issue_data(par, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) par->board->set_ctl(par, BS_CS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) par->board->mmio_write(par, BS_MMIO_DATA, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) par->board->mmio_write(par, BS_MMIO_DATA, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (par->board->mmio_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) broadsheet_mmio_write_reg(par, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) broadsheet_gpio_write_reg(par, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return broadsheet_get_data(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* functions for waveform manipulation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return broadsheet_read_reg(par, 0x000A) & 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int broadsheet_setup_plls(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int retry_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* disable arral saemipu mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) broadsheet_write_reg(par, 0x0006, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) broadsheet_write_reg(par, 0x0010, 0x0004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) broadsheet_write_reg(par, 0x0012, 0x5949);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) broadsheet_write_reg(par, 0x0014, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) broadsheet_write_reg(par, 0x0016, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (retry_count++ > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } while (!is_broadsheet_pll_locked(par));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) tmp = broadsheet_read_reg(par, 0x0006);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) tmp &= ~0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) broadsheet_write_reg(par, 0x0006, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int broadsheet_setup_spi(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) broadsheet_write_reg(par, 0x0208, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) u16 *orig_sfmcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) *orig_sfmcd = broadsheet_read_reg(par, 0x0204);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) broadsheet_write_reg(par, 0x0204, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u16 reg, int bitnum, int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tmp = broadsheet_read_reg(par, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (((tmp >> bitnum) & 1) == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } while (timeout--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) broadsheet_write_reg(par, 0x0202, (data | 0x100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) broadsheet_write_reg(par, 0x0202, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tmp = broadsheet_read_reg(par, 0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *data = tmp & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) broadsheet_write_reg(par, 0x0208, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) err = broadsheet_spiflash_write_byte(par, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) err = broadsheet_spiflash_read_byte(par, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!(tmp & 0x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) } while (timeout--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) dev_err(par->info->device, "Timed out waiting for spiflash status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) failout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u8 op, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) broadsheet_write_reg(par, 0x0208, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) err = broadsheet_spiflash_write_byte(par, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) for (i = 2; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) tmp = ((addr >> (i * 8)) & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) err = broadsheet_spiflash_write_byte(par, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int *flash_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) u8 sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) err = broadsheet_spiflash_read_byte(par, &sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if ((sig != 0x10) && (sig != 0x11)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev_err(par->info->device, "Unexpected flash type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) *flash_type = sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) failout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) u16 *initial_sfmcd, int *flash_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) err = broadsheet_setup_plls(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) broadsheet_write_reg(par, 0x0106, 0x0203);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) err = broadsheet_setup_spi(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) err = broadsheet_setup_spiflash(par, initial_sfmcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return broadsheet_verify_spiflash(par, flash_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) broadsheet_write_reg(par, 0x0208, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) err = broadsheet_spiflash_write_byte(par, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err = broadsheet_spiflash_write_byte(par, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) broadsheet_spiflash_write_control(par, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) err = broadsheet_spiflash_wait_for_status(par, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int addr, int size, char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) err = broadsheet_spiflash_read_byte(par, &data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) failout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #define BS_SPIFLASH_PAGE_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int addr, const char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) broadsheet_spiflash_write_control(par, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) err = broadsheet_spiflash_write_byte(par, data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) broadsheet_write_reg(par, 0x0208, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) err = broadsheet_spiflash_wait_for_status(par, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) failout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int addr, const char *data, int sector_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * The caller must guarantee that the data to be rewritten is entirely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * contained within this sector. That is, data_start_addr + data_len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * must be less than sector_start_addr + sector_size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int sector_size, int data_start_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int data_len, const char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) char *sector_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int tail_start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int start_sector_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) sector_buffer = kzalloc(sector_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!sector_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* the start address of the sector is the 0th byte of that sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) start_sector_addr = (data_start_addr / sector_size) * sector_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * check if there is head data that we need to readback into our sector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * buffer first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (data_start_addr != start_sector_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * we need to read every byte up till the start address of our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * data and we put it into our sector buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) err = broadsheet_spiflash_read_range(par, start_sector_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) data_start_addr, sector_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* now we copy our data into the right place in the sector buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) memcpy(sector_buffer + data_start_addr, data, data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * now we check if there is a tail section of the sector that we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * readback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) tail_start_addr = (data_start_addr + data_len) % sector_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (tail_start_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int tail_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) tail_len = sector_size - tail_start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* now we read this tail into our sector buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) err = broadsheet_spiflash_read_range(par, tail_start_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) tail_len, sector_buffer + tail_start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* if we got here we have the full sector that we want to rewrite. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* first erase the sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* now write it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err = broadsheet_spiflash_write_sector(par, start_sector_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) sector_buffer, sector_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) kfree(sector_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) const u8 *wfm, int bytecount, int flash_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int sector_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) int cur_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int writecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) switch (flash_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) sector_size = 32*1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) case 0x11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) sector_size = 64*1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) while (bytecount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) cur_addr = wfm_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) maxlen = roundup(cur_addr, sector_size) - cur_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) writecount = min(bytecount, maxlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) err = broadsheet_spiflash_rewrite_sector(par, sector_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) cur_addr, writecount, wfm + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) offset += writecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) bytecount -= writecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) const u8 *wfm, size_t wfm_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u16 initial_sfmcd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int flash_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) goto failout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) failout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) broadsheet_write_reg(par, 0x0204, initial_sfmcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static ssize_t broadsheet_loadstore_waveform(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) const struct firmware *fw_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (len < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dev_err(dev, "Failed to get broadsheet waveform\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) goto err_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* try to enforce reasonable min max on waveform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) dev_err(dev, "Invalid waveform\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) goto err_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mutex_lock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) fw_entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mutex_unlock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) dev_err(dev, "Failed to store broadsheet waveform\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto err_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) err = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) err_fw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) release_firmware(fw_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) err_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) broadsheet_loadstore_waveform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* upper level functions that manipulate the display and other stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static void broadsheet_init_display(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) u16 args[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) int xres = par->info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) int yres = par->info->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) args[0] = panel_table[par->panel_index].w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) args[1] = panel_table[par->panel_index].h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) args[2] = panel_table[par->panel_index].sdcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) args[3] = panel_table[par->panel_index].gdcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) args[4] = panel_table[par->panel_index].lutfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* did the controller really set it? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) args[0] = panel_table[par->panel_index].fsynclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) args[1] = panel_table[par->panel_index].fendfbegin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) args[2] = panel_table[par->panel_index].lsynclen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) args[3] = panel_table[par->panel_index].lendlbegin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) args[4] = panel_table[par->panel_index].pixclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) broadsheet_write_reg32(par, 0x310, xres*yres*2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* setup waveform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) args[0] = 0x886;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) args[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) broadsheet_write_reg(par, 0x330, 0x84);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) args[0] = (0x3 << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) args[0] = 0x154;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) broadsheet_burst_write(par, (panel_table[par->panel_index].w *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) panel_table[par->panel_index].h)/2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) (u16 *) par->info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) broadsheet_send_command(par, BS_CMD_LD_IMG_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) args[0] = 0x4300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static void broadsheet_identify(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) u16 rev, prc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct device *dev = par->info->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) rev = broadsheet_read_reg(par, BS_REG_REV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) prc = broadsheet_read_reg(par, BS_REG_PRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (prc != 0x0047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (rev != 0x0100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) dev_warn(dev, "Unrecognized Broadsheet Revision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static void broadsheet_init(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* the controller needs a second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) broadsheet_init_display(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) u16 y1, u16 y2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) u16 args[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) unsigned char *buf = (unsigned char *)par->info->screen_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) mutex_lock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) /* y1 must be a multiple of 4 so drop the lower bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) y1 &= 0xFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) y2 |= 0x0003;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) args[0] = 0x3 << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) args[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) args[2] = y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) args[3] = cpu_to_le16(par->info->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) args[4] = y2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) args[0] = 0x154;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) buf += y1 * par->info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) (u16 *) buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) broadsheet_send_command(par, BS_CMD_LD_IMG_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) args[0] = 0x4300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mutex_unlock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) u16 args[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) mutex_lock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) args[0] = 0x3 << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) args[0] = 0x154;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) broadsheet_burst_write(par, (panel_table[par->panel_index].w *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) panel_table[par->panel_index].h)/2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) (u16 *) par->info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) broadsheet_send_command(par, BS_CMD_LD_IMG_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) args[0] = 0x4300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) par->board->wait_for_rdy(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mutex_unlock(&(par->io_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* this is called back from the deferred io workqueue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct list_head *pagelist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) u16 y1 = 0, h = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int prev_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct page *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct fb_deferred_io *fbdefio = info->fbdefio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int h_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) u16 yres = info->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) u16 xres = info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* height increment is fixed per page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* walk the written page list and swizzle the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) list_for_each_entry(cur, &fbdefio->pagelist, lru) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (prev_index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* just starting so assign first page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) y1 = (cur->index << PAGE_SHIFT) / xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) h = h_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) } else if ((prev_index + 1) == cur->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* this page is consecutive so increase our height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) h += h_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /* page not consecutive, issue previous update first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) /* start over with our non consecutive page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) y1 = (cur->index << PAGE_SHIFT) / xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) h = h_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) prev_index = cur->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* if we still have any pages to update we do so now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (h >= yres) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* its a full screen update, just do it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) broadsheetfb_dpy_update(info->par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) broadsheetfb_dpy_update_pages(info->par, y1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) min((u16) (y1 + h), yres));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static void broadsheetfb_fillrect(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) sys_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) broadsheetfb_dpy_update(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static void broadsheetfb_copyarea(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) sys_copyarea(info, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) broadsheetfb_dpy_update(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static void broadsheetfb_imageblit(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) sys_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) broadsheetfb_dpy_update(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * this is the slow path from userspace. they can seek and write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * the fb. it's inefficient to do anything less than a full screen draw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) unsigned long p = *ppos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) void *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unsigned long total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (info->state != FBINFO_STATE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) total_size = info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (p > total_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (count > total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) err = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) count = total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (count + p > total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) err = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) count = total_size - p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dst = (void *)(info->screen_base + p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (copy_from_user(dst, buf, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) *ppos += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) broadsheetfb_dpy_update(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return (err) ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static const struct fb_ops broadsheetfb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .fb_read = fb_sys_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) .fb_write = broadsheetfb_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) .fb_fillrect = broadsheetfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) .fb_copyarea = broadsheetfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) .fb_imageblit = broadsheetfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static struct fb_deferred_io broadsheetfb_defio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .delay = HZ/4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .deferred_io = broadsheetfb_dpy_deferred_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int broadsheetfb_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct broadsheet_board *board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int videomemorysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) unsigned char *videomemory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) struct broadsheetfb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) int dpyw, dpyh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) int panel_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) /* pick up board specific routines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) board = dev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (!board)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* try to count device specific driver, if can't, platform recalls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (!try_module_get(board->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) switch (board->get_panel_type()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) case 37:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) panel_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) case 97:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) panel_index = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) panel_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) dpyw = panel_table[panel_index].w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) dpyh = panel_table[panel_index].h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) videomemory = vzalloc(videomemorysize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (!videomemory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) goto err_fb_rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) info->screen_base = (char *)videomemory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) info->fbops = &broadsheetfb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) broadsheetfb_var.xres = dpyw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) broadsheetfb_var.yres = dpyh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) broadsheetfb_var.xres_virtual = dpyw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) broadsheetfb_var.yres_virtual = dpyh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) info->var = broadsheetfb_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) broadsheetfb_fix.line_length = dpyw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) info->fix = broadsheetfb_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) info->fix.smem_len = videomemorysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) par->panel_index = panel_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) par->info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) par->board = board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) par->write_reg = broadsheet_write_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) par->read_reg = broadsheet_read_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) init_waitqueue_head(&par->waitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) mutex_init(&par->io_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) info->fbdefio = &broadsheetfb_defio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) fb_deferred_io_init(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) retval = fb_alloc_cmap(&info->cmap, 16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) dev_err(&dev->dev, "Failed to allocate colormap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) goto err_vfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* set cmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) retval = par->board->setup_irq(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) goto err_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* this inits the dpy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) retval = board->init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) broadsheet_identify(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) broadsheet_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) retval = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) platform_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) goto err_unreg_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) videomemorysize >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err_unreg_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) err_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) board->cleanup(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) err_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) err_vfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) vfree(videomemory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) err_fb_rel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) module_put(board->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) static int broadsheetfb_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) struct broadsheetfb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) device_remove_file(info->dev, &dev_attr_loadstore_waveform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) fb_deferred_io_cleanup(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) par->board->cleanup(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) vfree((void *)info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) module_put(par->board->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static struct platform_driver broadsheetfb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .probe = broadsheetfb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .remove = broadsheetfb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) .name = "broadsheetfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) module_platform_driver(broadsheetfb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) MODULE_AUTHOR("Jaya Kumar");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) MODULE_LICENSE("GPL");