mirror of
https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
synced 2025-12-03 05:11:14 +08:00
add: 03_LCD/12_编程_引脚配置_基于STM32MP157
This commit is contained in:
@@ -63,6 +63,7 @@ git clone https://e.coding.net/weidongshan/doc_and_source_for_drivers.git
|
|||||||
* 2021.01.20 发布"LCD驱动":10\_分析内核自带的LCD驱动程序\_基于STM32MP157
|
* 2021.01.20 发布"LCD驱动":10\_分析内核自带的LCD驱动程序\_基于STM32MP157
|
||||||
* 2021.01.21 发布"LCD驱动":11\_编程\_LCD驱动程序框架\_使用设备树
|
* 2021.01.21 发布"LCD驱动":11\_编程\_LCD驱动程序框架\_使用设备树
|
||||||
* 2021.01.21 发布"LCD驱动":12\_编程\_引脚配置\_基于IMX6ULL
|
* 2021.01.21 发布"LCD驱动":12\_编程\_引脚配置\_基于IMX6ULL
|
||||||
|
* 2021.01.22 发布"LCD驱动":12\_编程\_配置引脚\_基于STM32MP157
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
64
STM32MP157/doc_pic/03_LCD/12_编程_配置引脚_基于STM32MP157.md
Normal file
64
STM32MP157/doc_pic/03_LCD/12_编程_配置引脚_基于STM32MP157.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
## 编程\_配置引脚\_基于STM32MP157
|
||||||
|
|
||||||
|
参考资料,GIT仓库里:
|
||||||
|
|
||||||
|
* 芯片资料
|
||||||
|
|
||||||
|
* `STM32MP157\开发板配套资料\datasheeet\02_Core_board(核心板)\CPU\CPU开发参考手册\DM00327659.pdf`
|
||||||
|
* `《35 LCD-TFT display controller (LTDC)》`
|
||||||
|
|
||||||
|
* STM32MP157的LCD裸机程序
|
||||||
|
|
||||||
|
* `STM32MP157\source\A7\03_LCD\05_参考的裸机源码\03_font_test`
|
||||||
|
|
||||||
|
* 内核自带的STM32MP157 LCD驱动程序
|
||||||
|
* 驱动源码:
|
||||||
|
|
||||||
|
* LCD相关:`Linux-5.4\drivers\gpu\drm\panel\panel-myir070tft.c`
|
||||||
|
* LCD控制器相关:`Linux-5.4\drivers\gpu\drm\stm\ltdc.c`
|
||||||
|
* GPU相关:`Linux-5.4\drivers\gpu\drm\stm\drv.c`
|
||||||
|
* 设备树:
|
||||||
|
* `Linux-5.4/arch/arm/boot/dts/stm32mp157c-100ask-512d-lcd-v1.dts`
|
||||||
|
* `Linux-5.4/arch/arm/boot/dts/stm32mp151.dtsi`
|
||||||
|
* `Linux-5.4/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi`
|
||||||
|
|
||||||
|
* 本节视频编写好的代码
|
||||||
|
|
||||||
|
* `STM32MP157\source\A7\03_LCD\07_lcd_drv_pin_config_use_devicetree`
|
||||||
|
|
||||||
|
* 引脚配置工具/设备树生成工具
|
||||||
|
|
||||||
|
* 打开:http://download.100ask.net/
|
||||||
|
* 找到开发板:"100ASK_STM32MP157_PRO开发板"
|
||||||
|
* 下载开发板配套资料
|
||||||
|
* 下载完后,工具在如下目录里:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 1. 硬件相关的操作
|
||||||
|
|
||||||
|
LCD驱动程序的核心就是:
|
||||||
|
|
||||||
|
* 分配fb_info
|
||||||
|
* 设置fb_info
|
||||||
|
* 注册fb_info
|
||||||
|
* 硬件相关的设置
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
硬件相关的设置又可以分为3部分:
|
||||||
|
* 引脚设置
|
||||||
|
* 时钟设置
|
||||||
|
* LCD控制器设置
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 2. 引脚配置
|
||||||
|
|
||||||
|
主要使用pinctrl子系统把引脚配置为LCD功能,对于背光引脚等使用GPIO子系统的函数控制它的输出电平。
|
||||||
|
|
||||||
|
#### 2.1 使用pinctrl配置LCD引脚
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2.2 使用GPIO子系统控制背光
|
||||||
BIN
STM32MP157/doc_pic/03_LCD/12_编程_配置引脚_基于STM32MP157.tif
Normal file
BIN
STM32MP157/doc_pic/03_LCD/12_编程_配置引脚_基于STM32MP157.tif
Normal file
Binary file not shown.
BIN
STM32MP157/doc_pic/03_LCD/pic/02_LCD驱动/041_pins_tools.png
Normal file
BIN
STM32MP157/doc_pic/03_LCD/pic/02_LCD驱动/041_pins_tools.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,212 @@
|
|||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include <asm/div64.h>
|
||||||
|
|
||||||
|
#include <asm/mach/map.h>
|
||||||
|
|
||||||
|
struct lcd_regs {
|
||||||
|
volatile unsigned int fb_base_phys;
|
||||||
|
volatile unsigned int fb_xres;
|
||||||
|
volatile unsigned int fb_yres;
|
||||||
|
volatile unsigned int fb_bpp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct lcd_regs *mylcd_regs;
|
||||||
|
|
||||||
|
static struct fb_info *myfb_info;
|
||||||
|
|
||||||
|
static unsigned int pseudo_palette[16];
|
||||||
|
|
||||||
|
static struct gpio_desc *bl_gpio;
|
||||||
|
|
||||||
|
|
||||||
|
/* from pxafb.c */
|
||||||
|
static inline unsigned int chan_to_field(unsigned int chan,
|
||||||
|
struct fb_bitfield *bf)
|
||||||
|
{
|
||||||
|
chan &= 0xffff;
|
||||||
|
chan >>= 16 - bf->length;
|
||||||
|
return chan << bf->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mylcd_setcolreg(unsigned regno,
|
||||||
|
unsigned red, unsigned green, unsigned blue,
|
||||||
|
unsigned transp, struct fb_info *info)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
/* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",
|
||||||
|
regno, red, green, blue); */
|
||||||
|
|
||||||
|
switch (info->fix.visual) {
|
||||||
|
case FB_VISUAL_TRUECOLOR:
|
||||||
|
/* true-colour, use pseudo-palette */
|
||||||
|
|
||||||
|
if (regno < 16) {
|
||||||
|
u32 *pal = info->pseudo_palette;
|
||||||
|
|
||||||
|
val = chan_to_field(red, &info->var.red);
|
||||||
|
val |= chan_to_field(green, &info->var.green);
|
||||||
|
val |= chan_to_field(blue, &info->var.blue);
|
||||||
|
|
||||||
|
pal[regno] = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1; /* unknown type */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct fb_ops myfb_ops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.fb_setcolreg = mylcd_setcolreg,
|
||||||
|
.fb_fillrect = cfb_fillrect,
|
||||||
|
.fb_copyarea = cfb_copyarea,
|
||||||
|
.fb_imageblit = cfb_imageblit,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mylcd_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
dma_addr_t phy_addr;
|
||||||
|
|
||||||
|
/* get gpio from device tree */
|
||||||
|
bl_gpio = gpiod_get(&pdev->dev, "backlight", 0);
|
||||||
|
|
||||||
|
/* config bl_gpio as output */
|
||||||
|
gpiod_direction_output(bl_gpio, 1);
|
||||||
|
|
||||||
|
/* set val: gpiod_set_value(bl_gpio, status); */
|
||||||
|
|
||||||
|
/* 1.1 分配fb_info */
|
||||||
|
myfb_info = framebuffer_alloc(0, NULL);
|
||||||
|
|
||||||
|
/* 1.2 设置fb_info */
|
||||||
|
/* a. var : LCD分辨率、颜色格式 */
|
||||||
|
myfb_info->var.xres_virtual = myfb_info->var.xres = 500;
|
||||||
|
myfb_info->var.yres_virtual = myfb_info->var.yres = 300;
|
||||||
|
|
||||||
|
myfb_info->var.bits_per_pixel = 16; /* rgb565 */
|
||||||
|
myfb_info->var.red.offset = 11;
|
||||||
|
myfb_info->var.red.length = 5;
|
||||||
|
|
||||||
|
myfb_info->var.green.offset = 5;
|
||||||
|
myfb_info->var.green.length = 6;
|
||||||
|
|
||||||
|
myfb_info->var.blue.offset = 0;
|
||||||
|
myfb_info->var.blue.length = 5;
|
||||||
|
|
||||||
|
|
||||||
|
/* b. fix */
|
||||||
|
strcpy(myfb_info->fix.id, "100ask_lcd");
|
||||||
|
myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * myfb_info->var.bits_per_pixel / 8;
|
||||||
|
if (myfb_info->var.bits_per_pixel == 24)
|
||||||
|
myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * 4;
|
||||||
|
|
||||||
|
|
||||||
|
/* fb的虚拟地址 */
|
||||||
|
myfb_info->screen_base = dma_alloc_wc(NULL, myfb_info->fix.smem_len, &phy_addr,
|
||||||
|
GFP_KERNEL);
|
||||||
|
myfb_info->fix.smem_start = phy_addr; /* fb的物理地址 */
|
||||||
|
|
||||||
|
myfb_info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||||
|
myfb_info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||||
|
|
||||||
|
myfb_info->fix.line_length = myfb_info->var.xres * myfb_info->var.bits_per_pixel / 8;
|
||||||
|
if (myfb_info->var.bits_per_pixel == 24)
|
||||||
|
myfb_info->fix.line_length = myfb_info->var.xres * 4;
|
||||||
|
|
||||||
|
|
||||||
|
/* c. fbops */
|
||||||
|
myfb_info->fbops = &myfb_ops;
|
||||||
|
myfb_info->pseudo_palette = pseudo_palette;
|
||||||
|
|
||||||
|
|
||||||
|
/* 1.3 注册fb_info */
|
||||||
|
register_framebuffer(myfb_info);
|
||||||
|
|
||||||
|
/* 1.4 硬件操作 */
|
||||||
|
mylcd_regs = ioremap(0x021C8000, sizeof(struct lcd_regs));
|
||||||
|
mylcd_regs->fb_base_phys = phy_addr;
|
||||||
|
mylcd_regs->fb_xres = 500;
|
||||||
|
mylcd_regs->fb_yres = 300;
|
||||||
|
mylcd_regs->fb_bpp = 16;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mylcd_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
/* 反过来操作 */
|
||||||
|
/* 2.1 反注册fb_info */
|
||||||
|
unregister_framebuffer(myfb_info);
|
||||||
|
|
||||||
|
/* 2.2 释放fb_info */
|
||||||
|
framebuffer_release(myfb_info);
|
||||||
|
|
||||||
|
iounmap(mylcd_regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct of_device_id mylcd_of_match[] = {
|
||||||
|
{ .compatible = "100ask,lcd_drv", },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, simplefb_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver mylcd_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "mylcd",
|
||||||
|
.of_match_table = mylcd_of_match,
|
||||||
|
},
|
||||||
|
.probe = mylcd_probe,
|
||||||
|
.remove = mylcd_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init lcd_drv_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
ret = platform_driver_register(&mylcd_driver);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. 出口 */
|
||||||
|
static void __exit lcd_drv_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&mylcd_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module_init(lcd_drv_init);
|
||||||
|
module_exit(lcd_drv_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("www.100ask.net");
|
||||||
|
MODULE_DESCRIPTION("Framebuffer driver for the linux");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
|
||||||
|
/*
|
||||||
|
* Copyright (C) 100ASK 2020 - All Rights Reserved
|
||||||
|
* Author: 100ask
|
||||||
|
* support: weidongshan@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
#include "stm32mp157c-100ask-512d-v1.dts"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "100ASK YA157C v2 www.100ask.com";
|
||||||
|
compatible = "st,stm32mp157c-100ask-512d-v1", "st,stm32mp157";
|
||||||
|
|
||||||
|
|
||||||
|
framebuffer-mylcd {
|
||||||
|
compatible = "100ask,lcd_drv";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <<dc_pins_a>;
|
||||||
|
backlight-gpios = <&gpioe 11 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*LCD Panel*/
|
||||||
|
panel {
|
||||||
|
compatible = "myir,070tft";
|
||||||
|
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-parent = <&gpioe>;
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <<dc_pins_a>;
|
||||||
|
pinctrl-1 = <<dc_pins_sleep_a>;
|
||||||
|
//reset-gpios = <&gpioe 12 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
backlight = <&panel_backlight>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
port {
|
||||||
|
panel_in: endpoint {
|
||||||
|
remote-endpoint = <<dc_ep0_out>;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&spi5 {
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&spi5_pins_a>;
|
||||||
|
pinctrl-1 = <&spi5_sleep_pins_a>;
|
||||||
|
status = "okay";
|
||||||
|
cs-gpios = <&gpioh 5 GPIO_ACTIVE_LOW>;
|
||||||
|
spidev: icm20608@0{
|
||||||
|
compatible = "invensense,icm20608";
|
||||||
|
interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-parent = <&gpioz>;
|
||||||
|
spi-max-frequency = <8000000>;
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* test HDMI*/
|
||||||
|
<dc {
|
||||||
|
status = "okay";
|
||||||
|
port {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ltdc_ep1_out: endpoint@1 {
|
||||||
|
reg = <1>;
|
||||||
|
remote-endpoint = <&sii9022_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*HDMI*/
|
||||||
|
&i2c4 {
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
hdmi-transmitter@40 { // use a dummy device
|
||||||
|
compatible = "sil,sii9022";
|
||||||
|
reg = <0x40>;
|
||||||
|
reset-gpios = <&gpiob 10 GPIO_ACTIVE_LOW>;
|
||||||
|
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-parent = <&gpiob>;
|
||||||
|
//pinctrl-names = "default", "sleep";
|
||||||
|
//pinctrl-0 = <<dc_pins_a>;
|
||||||
|
//pinctrl-1 = <<dc_pins_sleep_a>;
|
||||||
|
status = "disabled";
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
sii9022_in: endpoint {
|
||||||
|
remote-endpoint = <<dc_ep1_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
sii902x: sii902x@39 {
|
||||||
|
compatible = "SiI,sii902x";
|
||||||
|
reset-gpios = <&gpiob 10 GPIO_ACTIVE_LOW>;
|
||||||
|
//pinctrl-names = "default";
|
||||||
|
//pinctrl-0 = <&pinctrl_sii902x>;
|
||||||
|
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-parent = <&gpiob>;
|
||||||
|
mode_str ="1280x720M@60";
|
||||||
|
bits-per-pixel = <16>;
|
||||||
|
reg = <0x39>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2s2 {
|
||||||
|
status = "disable";
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*test LCD*/
|
||||||
|
<dc {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
port {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ltdc_ep0_out: endpoint@0 {
|
||||||
|
reg = <0>;
|
||||||
|
remote-endpoint = <&panel_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user