linux/drivers/video/omap2/displays/panel-n8x0.c
<<
>>
Prefs
   1/* #define DEBUG */
   2
   3#include <linux/module.h>
   4#include <linux/delay.h>
   5#include <linux/slab.h>
   6#include <linux/gpio.h>
   7#include <linux/spi/spi.h>
   8#include <linux/backlight.h>
   9#include <linux/fb.h>
  10
  11#include <video/omapdss.h>
  12#include <video/omap-panel-n8x0.h>
  13
  14#define BLIZZARD_REV_CODE                      0x00
  15#define BLIZZARD_CONFIG                        0x02
  16#define BLIZZARD_PLL_DIV                       0x04
  17#define BLIZZARD_PLL_LOCK_RANGE                0x06
  18#define BLIZZARD_PLL_CLOCK_SYNTH_0             0x08
  19#define BLIZZARD_PLL_CLOCK_SYNTH_1             0x0a
  20#define BLIZZARD_PLL_MODE                      0x0c
  21#define BLIZZARD_CLK_SRC                       0x0e
  22#define BLIZZARD_MEM_BANK0_ACTIVATE            0x10
  23#define BLIZZARD_MEM_BANK0_STATUS              0x14
  24#define BLIZZARD_PANEL_CONFIGURATION           0x28
  25#define BLIZZARD_HDISP                         0x2a
  26#define BLIZZARD_HNDP                          0x2c
  27#define BLIZZARD_VDISP0                        0x2e
  28#define BLIZZARD_VDISP1                        0x30
  29#define BLIZZARD_VNDP                          0x32
  30#define BLIZZARD_HSW                           0x34
  31#define BLIZZARD_VSW                           0x38
  32#define BLIZZARD_DISPLAY_MODE                  0x68
  33#define BLIZZARD_INPUT_WIN_X_START_0           0x6c
  34#define BLIZZARD_DATA_SOURCE_SELECT            0x8e
  35#define BLIZZARD_DISP_MEM_DATA_PORT            0x90
  36#define BLIZZARD_DISP_MEM_READ_ADDR0           0x92
  37#define BLIZZARD_POWER_SAVE                    0xE6
  38#define BLIZZARD_NDISP_CTRL_STATUS             0xE8
  39
  40/* Data source select */
  41/* For S1D13745 */
  42#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND       0x00
  43#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE      0x01
  44#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE       0x04
  45#define BLIZZARD_SRC_DISABLE_OVERLAY            0x05
  46/* For S1D13744 */
  47#define BLIZZARD_SRC_WRITE_LCD                  0x00
  48#define BLIZZARD_SRC_BLT_LCD                    0x06
  49
  50#define BLIZZARD_COLOR_RGB565                   0x01
  51#define BLIZZARD_COLOR_YUV420                   0x09
  52
  53#define BLIZZARD_VERSION_S1D13745               0x01    /* Hailstorm */
  54#define BLIZZARD_VERSION_S1D13744               0x02    /* Blizzard */
  55
  56#define MIPID_CMD_READ_DISP_ID          0x04
  57#define MIPID_CMD_READ_RED              0x06
  58#define MIPID_CMD_READ_GREEN            0x07
  59#define MIPID_CMD_READ_BLUE             0x08
  60#define MIPID_CMD_READ_DISP_STATUS      0x09
  61#define MIPID_CMD_RDDSDR                0x0F
  62#define MIPID_CMD_SLEEP_IN              0x10
  63#define MIPID_CMD_SLEEP_OUT             0x11
  64#define MIPID_CMD_DISP_OFF              0x28
  65#define MIPID_CMD_DISP_ON               0x29
  66
  67static struct panel_drv_data {
  68        struct mutex lock;
  69
  70        struct omap_dss_device *dssdev;
  71        struct spi_device *spidev;
  72        struct backlight_device *bldev;
  73
  74        int blizzard_ver;
  75} s_drv_data;
  76
  77
  78static inline
  79struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
  80{
  81        return dssdev->data;
  82}
  83
  84static inline
  85struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
  86{
  87        return &s_drv_data;
  88}
  89
  90
  91static inline void blizzard_cmd(u8 cmd)
  92{
  93        omap_rfbi_write_command(&cmd, 1);
  94}
  95
  96static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
  97{
  98        omap_rfbi_write_command(&cmd, 1);
  99        omap_rfbi_write_data(buf, len);
 100}
 101
 102static inline void blizzard_read(u8 cmd, u8 *buf, int len)
 103{
 104        omap_rfbi_write_command(&cmd, 1);
 105        omap_rfbi_read_data(buf, len);
 106}
 107
 108static u8 blizzard_read_reg(u8 cmd)
 109{
 110        u8 data;
 111        blizzard_read(cmd, &data, 1);
 112        return data;
 113}
 114
 115static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
 116                int x, int y, int w, int h)
 117{
 118        struct panel_drv_data *ddata = get_drv_data(dssdev);
 119        u8 tmp[18];
 120        int x_end, y_end;
 121
 122        x_end = x + w - 1;
 123        y_end = y + h - 1;
 124
 125        tmp[0] = x;
 126        tmp[1] = x >> 8;
 127        tmp[2] = y;
 128        tmp[3] = y >> 8;
 129        tmp[4] = x_end;
 130        tmp[5] = x_end >> 8;
 131        tmp[6] = y_end;
 132        tmp[7] = y_end >> 8;
 133
 134        /* scaling? */
 135        tmp[8] = x;
 136        tmp[9] = x >> 8;
 137        tmp[10] = y;
 138        tmp[11] = y >> 8;
 139        tmp[12] = x_end;
 140        tmp[13] = x_end >> 8;
 141        tmp[14] = y_end;
 142        tmp[15] = y_end >> 8;
 143
 144        tmp[16] = BLIZZARD_COLOR_RGB565;
 145
 146        if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
 147                tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
 148        else
 149                tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
 150                        BLIZZARD_SRC_WRITE_LCD :
 151                        BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
 152
 153        omapdss_rfbi_set_pixel_size(dssdev, 16);
 154        omapdss_rfbi_set_data_lines(dssdev, 8);
 155
 156        omap_rfbi_configure(dssdev);
 157
 158        blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
 159
 160        omapdss_rfbi_set_pixel_size(dssdev, 16);
 161        omapdss_rfbi_set_data_lines(dssdev, 16);
 162
 163        omap_rfbi_configure(dssdev);
 164}
 165
 166static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
 167                int wlen, u8 *rbuf, int rlen)
 168{
 169        struct spi_message      m;
 170        struct spi_transfer     *x, xfer[4];
 171        u16                     w;
 172        int                     r;
 173
 174        spi_message_init(&m);
 175
 176        memset(xfer, 0, sizeof(xfer));
 177        x = &xfer[0];
 178
 179        cmd &=  0xff;
 180        x->tx_buf               = &cmd;
 181        x->bits_per_word        = 9;
 182        x->len                  = 2;
 183        spi_message_add_tail(x, &m);
 184
 185        if (wlen) {
 186                x++;
 187                x->tx_buf               = wbuf;
 188                x->len                  = wlen;
 189                x->bits_per_word        = 9;
 190                spi_message_add_tail(x, &m);
 191        }
 192
 193        if (rlen) {
 194                x++;
 195                x->rx_buf       = &w;
 196                x->len          = 1;
 197                spi_message_add_tail(x, &m);
 198
 199                if (rlen > 1) {
 200                        /* Arrange for the extra clock before the first
 201                         * data bit.
 202                         */
 203                        x->bits_per_word = 9;
 204                        x->len           = 2;
 205
 206                        x++;
 207                        x->rx_buf        = &rbuf[1];
 208                        x->len           = rlen - 1;
 209                        spi_message_add_tail(x, &m);
 210                }
 211        }
 212
 213        r = spi_sync(spi, &m);
 214        if (r < 0)
 215                dev_dbg(&spi->dev, "spi_sync %d\n", r);
 216
 217        if (rlen)
 218                rbuf[0] = w & 0xff;
 219}
 220
 221static inline void mipid_cmd(struct spi_device *spi, int cmd)
 222{
 223        mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
 224}
 225
 226static inline void mipid_write(struct spi_device *spi,
 227                int reg, const u8 *buf, int len)
 228{
 229        mipid_transfer(spi, reg, buf, len, NULL, 0);
 230}
 231
 232static inline void mipid_read(struct spi_device *spi,
 233                int reg, u8 *buf, int len)
 234{
 235        mipid_transfer(spi, reg, NULL, 0, buf, len);
 236}
 237
 238static void set_data_lines(struct spi_device *spi, int data_lines)
 239{
 240        u16 par;
 241
 242        switch (data_lines) {
 243        case 16:
 244                par = 0x150;
 245                break;
 246        case 18:
 247                par = 0x160;
 248                break;
 249        case 24:
 250                par = 0x170;
 251                break;
 252        }
 253
 254        mipid_write(spi, 0x3a, (u8 *)&par, 2);
 255}
 256
 257static void send_init_string(struct spi_device *spi)
 258{
 259        u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
 260        mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
 261}
 262
 263static void send_display_on(struct spi_device *spi)
 264{
 265        mipid_cmd(spi, MIPID_CMD_DISP_ON);
 266}
 267
 268static void send_display_off(struct spi_device *spi)
 269{
 270        mipid_cmd(spi, MIPID_CMD_DISP_OFF);
 271}
 272
 273static void send_sleep_out(struct spi_device *spi)
 274{
 275        mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
 276        msleep(120);
 277}
 278
 279static void send_sleep_in(struct spi_device *spi)
 280{
 281        mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
 282        msleep(50);
 283}
 284
 285static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
 286{
 287        int r;
 288        struct panel_n8x0_data *bdata = get_board_data(dssdev);
 289        struct panel_drv_data *ddata = get_drv_data(dssdev);
 290        struct spi_device *spi = ddata->spidev;
 291        u8 rev, conf;
 292        u8 display_id[3];
 293        const char *panel_name;
 294
 295        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
 296                return 0;
 297
 298        gpio_direction_output(bdata->ctrl_pwrdown, 1);
 299
 300        if (bdata->platform_enable) {
 301                r = bdata->platform_enable(dssdev);
 302                if (r)
 303                        goto err_plat_en;
 304        }
 305
 306        omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
 307                dssdev->panel.timings.y_res);
 308        omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
 309        omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
 310        omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
 311
 312        r = omapdss_rfbi_display_enable(dssdev);
 313        if (r)
 314                goto err_rfbi_en;
 315
 316        rev = blizzard_read_reg(BLIZZARD_REV_CODE);
 317        conf = blizzard_read_reg(BLIZZARD_CONFIG);
 318
 319        switch (rev & 0xfc) {
 320        case 0x9c:
 321                ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
 322                dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
 323                        "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
 324                break;
 325        case 0xa4:
 326                ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
 327                dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
 328                        "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
 329                break;
 330        default:
 331                dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
 332                r = -ENODEV;
 333                goto err_inv_chip;
 334        }
 335
 336        /* panel */
 337
 338        gpio_direction_output(bdata->panel_reset, 1);
 339
 340        mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
 341        dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
 342                        display_id[0], display_id[1], display_id[2]);
 343
 344        switch (display_id[0]) {
 345        case 0x45:
 346                panel_name = "lph8923";
 347                break;
 348        case 0x83:
 349                panel_name = "ls041y3";
 350                break;
 351        default:
 352                dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
 353                                display_id[0]);
 354                r = -ENODEV;
 355                goto err_inv_panel;
 356        }
 357
 358        dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
 359                        panel_name, display_id[1]);
 360
 361        send_sleep_out(spi);
 362        send_init_string(spi);
 363        set_data_lines(spi, 24);
 364        send_display_on(spi);
 365
 366        return 0;
 367
 368err_inv_panel:
 369        /*
 370         * HACK: we should turn off the panel here, but there is some problem
 371         * with the initialization sequence, and we fail to init the panel if we
 372         * have turned it off
 373         */
 374        /* gpio_direction_output(bdata->panel_reset, 0); */
 375err_inv_chip:
 376        omapdss_rfbi_display_disable(dssdev);
 377err_rfbi_en:
 378        if (bdata->platform_disable)
 379                bdata->platform_disable(dssdev);
 380err_plat_en:
 381        gpio_direction_output(bdata->ctrl_pwrdown, 0);
 382        return r;
 383}
 384
 385static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
 386{
 387        struct panel_n8x0_data *bdata = get_board_data(dssdev);
 388        struct panel_drv_data *ddata = get_drv_data(dssdev);
 389        struct spi_device *spi = ddata->spidev;
 390
 391        if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 392                return;
 393
 394        send_display_off(spi);
 395        send_sleep_in(spi);
 396
 397        if (bdata->platform_disable)
 398                bdata->platform_disable(dssdev);
 399
 400        /*
 401         * HACK: we should turn off the panel here, but there is some problem
 402         * with the initialization sequence, and we fail to init the panel if we
 403         * have turned it off
 404         */
 405        /* gpio_direction_output(bdata->panel_reset, 0); */
 406        gpio_direction_output(bdata->ctrl_pwrdown, 0);
 407        omapdss_rfbi_display_disable(dssdev);
 408}
 409
 410static const struct rfbi_timings n8x0_panel_timings = {
 411        .cs_on_time     = 0,
 412
 413        .we_on_time     = 9000,
 414        .we_off_time    = 18000,
 415        .we_cycle_time  = 36000,
 416
 417        .re_on_time     = 9000,
 418        .re_off_time    = 27000,
 419        .re_cycle_time  = 36000,
 420
 421        .access_time    = 27000,
 422        .cs_off_time    = 36000,
 423
 424        .cs_pulse_width = 0,
 425};
 426
 427static int n8x0_bl_update_status(struct backlight_device *dev)
 428{
 429        struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
 430        struct panel_n8x0_data *bdata = get_board_data(dssdev);
 431        struct panel_drv_data *ddata = get_drv_data(dssdev);
 432        int r;
 433        int level;
 434
 435        mutex_lock(&ddata->lock);
 436
 437        if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
 438                        dev->props.power == FB_BLANK_UNBLANK)
 439                level = dev->props.brightness;
 440        else
 441                level = 0;
 442
 443        dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
 444
 445        if (!bdata->set_backlight)
 446                r = -EINVAL;
 447        else
 448                r = bdata->set_backlight(dssdev, level);
 449
 450        mutex_unlock(&ddata->lock);
 451
 452        return r;
 453}
 454
 455static int n8x0_bl_get_intensity(struct backlight_device *dev)
 456{
 457        if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
 458                        dev->props.power == FB_BLANK_UNBLANK)
 459                return dev->props.brightness;
 460
 461        return 0;
 462}
 463
 464static const struct backlight_ops n8x0_bl_ops = {
 465        .get_brightness = n8x0_bl_get_intensity,
 466        .update_status  = n8x0_bl_update_status,
 467};
 468
 469static int n8x0_panel_probe(struct omap_dss_device *dssdev)
 470{
 471        struct panel_n8x0_data *bdata = get_board_data(dssdev);
 472        struct panel_drv_data *ddata;
 473        struct backlight_device *bldev;
 474        struct backlight_properties props;
 475        int r;
 476
 477        dev_dbg(&dssdev->dev, "probe\n");
 478
 479        if (!bdata)
 480                return -EINVAL;
 481
 482        s_drv_data.dssdev = dssdev;
 483
 484        ddata = &s_drv_data;
 485
 486        mutex_init(&ddata->lock);
 487
 488        dssdev->panel.timings.x_res = 800;
 489        dssdev->panel.timings.y_res = 480;
 490        dssdev->ctrl.pixel_size = 16;
 491        dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
 492        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 493
 494        memset(&props, 0, sizeof(props));
 495        props.max_brightness = 127;
 496        props.type = BACKLIGHT_PLATFORM;
 497        bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
 498                        dssdev, &n8x0_bl_ops, &props);
 499        if (IS_ERR(bldev)) {
 500                r = PTR_ERR(bldev);
 501                dev_err(&dssdev->dev, "register backlight failed\n");
 502                return r;
 503        }
 504
 505        ddata->bldev = bldev;
 506
 507        bldev->props.fb_blank = FB_BLANK_UNBLANK;
 508        bldev->props.power = FB_BLANK_UNBLANK;
 509        bldev->props.brightness = 127;
 510
 511        n8x0_bl_update_status(bldev);
 512
 513        return 0;
 514}
 515
 516static void n8x0_panel_remove(struct omap_dss_device *dssdev)
 517{
 518        struct panel_drv_data *ddata = get_drv_data(dssdev);
 519        struct backlight_device *bldev;
 520
 521        dev_dbg(&dssdev->dev, "remove\n");
 522
 523        bldev = ddata->bldev;
 524        bldev->props.power = FB_BLANK_POWERDOWN;
 525        n8x0_bl_update_status(bldev);
 526        backlight_device_unregister(bldev);
 527
 528        dev_set_drvdata(&dssdev->dev, NULL);
 529}
 530
 531static int n8x0_panel_enable(struct omap_dss_device *dssdev)
 532{
 533        struct panel_drv_data *ddata = get_drv_data(dssdev);
 534        int r;
 535
 536        dev_dbg(&dssdev->dev, "enable\n");
 537
 538        mutex_lock(&ddata->lock);
 539
 540        rfbi_bus_lock();
 541
 542        r = n8x0_panel_power_on(dssdev);
 543
 544        rfbi_bus_unlock();
 545
 546        if (r) {
 547                mutex_unlock(&ddata->lock);
 548                return r;
 549        }
 550
 551        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 552
 553        mutex_unlock(&ddata->lock);
 554
 555        return 0;
 556}
 557
 558static void n8x0_panel_disable(struct omap_dss_device *dssdev)
 559{
 560        struct panel_drv_data *ddata = get_drv_data(dssdev);
 561
 562        dev_dbg(&dssdev->dev, "disable\n");
 563
 564        mutex_lock(&ddata->lock);
 565
 566        rfbi_bus_lock();
 567
 568        n8x0_panel_power_off(dssdev);
 569
 570        rfbi_bus_unlock();
 571
 572        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 573
 574        mutex_unlock(&ddata->lock);
 575}
 576
 577static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
 578                u16 *xres, u16 *yres)
 579{
 580        *xres = dssdev->panel.timings.x_res;
 581        *yres = dssdev->panel.timings.y_res;
 582}
 583
 584static void update_done(void *data)
 585{
 586        rfbi_bus_unlock();
 587}
 588
 589static int n8x0_panel_update(struct omap_dss_device *dssdev,
 590                u16 x, u16 y, u16 w, u16 h)
 591{
 592        struct panel_drv_data *ddata = get_drv_data(dssdev);
 593        u16 dw, dh;
 594
 595        dev_dbg(&dssdev->dev, "update\n");
 596
 597        dw = dssdev->panel.timings.x_res;
 598        dh = dssdev->panel.timings.y_res;
 599
 600        if (x != 0 || y != 0 || w != dw || h != dh) {
 601                dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
 602                        x, y, w, h);
 603                return -EINVAL;
 604        }
 605
 606        mutex_lock(&ddata->lock);
 607        rfbi_bus_lock();
 608
 609        blizzard_ctrl_setup_update(dssdev, x, y, w, h);
 610
 611        omap_rfbi_update(dssdev, update_done, NULL);
 612
 613        mutex_unlock(&ddata->lock);
 614
 615        return 0;
 616}
 617
 618static int n8x0_panel_sync(struct omap_dss_device *dssdev)
 619{
 620        struct panel_drv_data *ddata = get_drv_data(dssdev);
 621
 622        dev_dbg(&dssdev->dev, "sync\n");
 623
 624        mutex_lock(&ddata->lock);
 625        rfbi_bus_lock();
 626        rfbi_bus_unlock();
 627        mutex_unlock(&ddata->lock);
 628
 629        return 0;
 630}
 631
 632static struct omap_dss_driver n8x0_panel_driver = {
 633        .probe          = n8x0_panel_probe,
 634        .remove         = n8x0_panel_remove,
 635
 636        .enable         = n8x0_panel_enable,
 637        .disable        = n8x0_panel_disable,
 638
 639        .update         = n8x0_panel_update,
 640        .sync           = n8x0_panel_sync,
 641
 642        .get_resolution = n8x0_panel_get_resolution,
 643        .get_recommended_bpp = omapdss_default_get_recommended_bpp,
 644
 645        .driver         = {
 646                .name   = "n8x0_panel",
 647                .owner  = THIS_MODULE,
 648        },
 649};
 650
 651/* PANEL */
 652
 653static int mipid_spi_probe(struct spi_device *spi)
 654{
 655        int r;
 656
 657        dev_dbg(&spi->dev, "mipid_spi_probe\n");
 658
 659        spi->mode = SPI_MODE_0;
 660
 661        s_drv_data.spidev = spi;
 662
 663        r = omap_dss_register_driver(&n8x0_panel_driver);
 664        if (r)
 665                pr_err("n8x0_panel: dss driver registration failed\n");
 666
 667        return r;
 668}
 669
 670static int mipid_spi_remove(struct spi_device *spi)
 671{
 672        dev_dbg(&spi->dev, "mipid_spi_remove\n");
 673        omap_dss_unregister_driver(&n8x0_panel_driver);
 674        return 0;
 675}
 676
 677static struct spi_driver mipid_spi_driver = {
 678        .driver = {
 679                .name   = "lcd_mipid",
 680                .owner  = THIS_MODULE,
 681        },
 682        .probe  = mipid_spi_probe,
 683        .remove = mipid_spi_remove,
 684};
 685module_spi_driver(mipid_spi_driver);
 686
 687MODULE_LICENSE("GPL");
 688