milkv4. Add LCD screen gc9306

Foreword

This chapter introduces how to add the LCD screen GC9306 driver.

Circuit diagram

dts

build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts

 & amp;spi2 {<!-- -->
status = "okay";

    /delete-node/ spidev@0;

gc9306: gc9306@0{<!-- -->
compatible = "sitronix,gc9306";
reg = <0>;
status = "okay";
spi-max-frequency = <48000000>;
spi-cpol;
spi-cpha;
rotate = <90>;
fps = <30>;
rgb;
buswidth = <8>;

//dc-gpios = < & amp;port 21 GPIO_ACTIVE_HIGH>; //DC
dc-gpios = < & amp;porta 23 GPIO_ACTIVE_HIGH>; //DC
reset-gpios = < & amp;porta 24 GPIO_ACTIVE_HIGH>; //RES
led-gpios = < & amp;porta 14 GPIO_ACTIVE_HIGH>; //BL

debug = <0x1>;
};

};

makefile

linux_5.10\drivers\staging\fbtft\Makefile

obj-$(CONFIG_FB_TFT_GC9306) + = fb_gc9306.o

config

linux_5.10\drivers\staging\fbtft\Kconfig

config FB_TFT_GC9306
tristate "FB driver for the GC9306 LCD Controller"
depends on FB_TFT
help
Generic Framebuffer support for GC9306

decofig

build\boards\cv180x\cv1800b_milkv_duo_sd\linux\cvitek_cv1800b_milkv_duo_sd_defconfig

CONFIG_FB_TFT_GC9306=y

Driver

linux_5.10\drivers\staging\fbtft\fb_gc9306.c

// SPDX-License-Identifier: GPL-2.0 +
/*
 * FB driver for the GC9306 LCD Controller
 *
 * Copyright (C) 2015 Dennis Menschel
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <video/mipi_display.h>

#include "fbtft.h"

#define DRVNAME "fb_gc9306"

#define GC9306_IPS_GAMMA \
    "02 00 00 1b 1f 0b\
" \
    "01 03 00 28 2b 0e\
" \
    "0b 08 3b 04 03 4c\
" \
    "0e 07 46 04 05 51\
" \
    "08 15 15 1f 22 0F\
" \
    "0b 13 11 1f 21 0F"

/**
 * init_display() - initialize the display controller
 *
 * @par: FBTFT parameter object
 *
 * Most of the commands in this init function set their parameters to the
 * same default values which are already in place after the display has been
 * powered up. (The main exception to this rule is the pixel format which
 * would default to 18 instead of 16 bit per pixel.)
 * Nonetheless, this sequence can be used as a template for concrete
 * displays which usually need some adjustments.
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int init_display(struct fbtft_par *par)
{<!-- -->
par->fbtftops.reset(par);//Hard reset

mdelay(50);

    //display control setting
    write_reg(par, 0xfe);
    write_reg(par, 0xef);
    write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0x48);//MX, MY, RGB mode refresh direction 48 vertical screen
    write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);//65k mode
    write_reg(par, 0xad,0x33);
    write_reg(par, 0xaf,0x55);
    write_reg(par, 0xae,0x2b);

    //GC9306 Power Sequence
    write_reg(par, 0xa4,0x44,0x44);
    write_reg(par, 0xa5,0x42,0x42);
    write_reg(par, 0xaa,0x88,0x88);
    write_reg(par, 0xae,0x2b);
    write_reg(par, 0xe8,0x11,0x0b);
    write_reg(par, 0xe3,0x01,0x10);
    write_reg(par, 0xff,0x61);
    write_reg(par, 0xac,0x00);
    write_reg(par, 0xaf,0x67);
    write_reg(par, 0xa6,0x2a,0x2a);
    write_reg(par, 0xa7,0x2b,0x2b);
    write_reg(par, 0xa8,0x18,0x18);
    write_reg(par, 0xa9,0x2a,0x2a);

    //display window 240X320 matching mode
    write_reg(par, 0x2a,0x00,0x00,0x00,0xef); //MIPI_DCS_SET_COLUMN_ADDRESS - 240
    write_reg(par, 0x2b,0x00,0x00,0x01,0x3f); //MIPI_DCS_SET_PAGE_ADDRESS - 320
    write_reg(par, 0x2c); //MIPI_DCS_WRITE_MEMORY_START

    //GC9306 Gamma Sequence
    write_reg(par, 0xF0,0x02,0x00,0x00,0x1b,0x1f,0x0b);
    write_reg(par, 0xF1,0x01,0x03,0x00,0x28,0x2b,0x0e);
    write_reg(par, 0xF2,0x0b,0x08,0x3b,0x04,0x03,0x4c);
    write_reg(par, 0xF3,0x0e,0x07,0x46,0x04,0x05,0x51);
    write_reg(par, 0xF4,0x08,0x15,0x15,0x1f,0x22,0x0F);
    write_reg(par, 0xF5,0x0b,0x13,0x11,0x1f,0x21,0x0F);

    /* Sleep Out */
    write_reg(par, 0x11); //MIPI_DCS_EXIT_SLEEP_MODE
    mdelay(100);

    write_reg(par, 0x2c); //MIPI_DCS_WRITE_MEMORY_START

    //luat_lcd_clear(par, BLACK);

    /* display on */
write_reg(par, 0x29); //MIPI_DCS_SET_DISPLAY_ON - 29
mdelay(100);

    return 0;
}

/**
 * set_var() - apply LCD properties like rotation and BGR mode
 *
 * @par: FBTFT parameter object
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int set_var(struct fbtft_par *par)
{<!-- -->
u8 madctl_par = 0;

if (par->bgr)
madctl_par =0x48;
switch (par->info->var.rotate) {<!-- -->
case 0:
madctl_par = 0x48;
break; //48
case 90:
madctl_par = 0xE8;
break;
case 180:
madctl_par =0x28;
break;
case 270:
madctl_par =0xF8;
break;
default:
return -EINVAL;
}
write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, madctl_par);
return 0;
}


/**
 * set_gamma() - set gamma curves
 *
 * @par: FBTFT parameter object
 * @curves: gamma curves
 *
 * Before the gamma curves are applied, they are preprocessed with a bitmask
 * to ensure syntactically correct input for the display controller.
 * This implies that the curves input parameter might be changed by this
 * function and that illegal gamma values are auto-corrected and not
 * reported as errors.
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int set_gamma(struct fbtft_par *par, u32 *curves)
{<!-- -->
    //GC9306 Gamma Sequence
    write_reg(par, 0xF0,0x02,0x00,0x00,0x1b,0x1f,0x0b);
    write_reg(par, 0xF1,0x01,0x03,0x00,0x28,0x2b,0x0e);
    write_reg(par, 0xF2,0x0b,0x08,0x3b,0x04,0x03,0x4c);
    write_reg(par, 0xF3,0x0e,0x07,0x46,0x04,0x05,0x51);
    write_reg(par, 0xF4,0x08,0x15,0x15,0x1f,0x22,0x0F);
    write_reg(par, 0xF5,0x0b,0x13,0x11,0x1f,0x21,0x0F);

return 0;
}

/**
 * blank() - blank the display
 *
 * @par: FBTFT parameter object
 * @on: whether to enable or disable blanking the display
 *
 * Return: 0 on success, < 0 if error occurred.
 */
static int blank(struct fbtft_par *par, bool on)
{<!-- -->
if (on)
write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
else
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
}

static struct fbtft_display display = {<!-- -->
.regwidth = 8,
.width = 240,
.height = 320,
.gamma_num = 6,
.gamma_len = 6,
.gamma = GC9306_IPS_GAMMA,
.fbtftops = {<!-- -->
.init_display = init_display,
.set_var = set_var,
.set_gamma = set_gamma,
.blank = blank,
},
};

FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,gc9306", & amp;display);

MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:gc9306");
MODULE_ALIAS("platform:gc9306");

MODULE_DESCRIPTION("FB driver for the GC9306 LCD Controller");
MODULE_AUTHOR("Dennis Menschel & amp; Youkai");
MODULE_LICENSE("GPL");

Test