Steward
分享是一種喜悅、更是一種幸福
掌機 - GCW Zero - 更換螢幕(3.5吋 IPS HX8363-A 解析度640x480)
司徒改造掌機的目的就是希望這台掌機可以更趨完美,而第一個改造的東西通常是屏幕,因為屏幕算是最直覺的第一影響因素,好不好只要一開機就可以知道,因此,司徒第一任務就是更換屏幕,而原本的屏幕解析度是320x240,司徒打算更換成更高解析度的屏幕,這樣的話,至少DOSBox可以顯示更精細的遊戲內容,因此,司徒從淘寶購買一片IPS 3.5" 640x480解析度的屏幕(RGB介面),如下所示:

drivers/video/displays/Kconfig
config PANEL_HX8363A
# TODO: Switch to tristate once the driver is a module.
bool "HX8363A based panel"
help
Select this if you are using a HX8363A LCD driver IC.
drivers/video/displays/Makefile
obj-$(CONFIG_PANEL_HX8363A) += panel-hx8363a.o
drivers/video/displays/panel-hx8363a.c
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gfp.h>
#include <linux/gpio.h>
#include <video/jzpanel.h>
#include <video/panel-hx8363a.h>
struct hx8363a {
struct hx8363a_platform_data *pdata;
};
static void hx8363a_send_cmd(struct hx8363a_platform_data *pdata, u8 data)
{
int bit;
gpio_direction_output(pdata->gpio_enable, 0);
gpio_direction_output(pdata->gpio_clock, 0);
gpio_direction_output(pdata->gpio_data, 0);
udelay(10);
gpio_direction_output(pdata->gpio_clock, 1);
udelay(10);
for (bit = 7; bit >= 0; bit--) {
gpio_direction_output(pdata->gpio_clock, 0);
gpio_direction_output(pdata->gpio_data, (data >> bit) & 1);
udelay(10);
gpio_direction_output(pdata->gpio_clock, 1);
udelay(10);
}
gpio_direction_output(pdata->gpio_enable, 1);
}
static void hx8363a_send_data(struct hx8363a_platform_data *pdata, u8 data)
{
int bit;
gpio_direction_output(pdata->gpio_enable, 0);
gpio_direction_output(pdata->gpio_clock, 0);
gpio_direction_output(pdata->gpio_data, 1);
udelay(10);
gpio_direction_output(pdata->gpio_clock, 1);
udelay(10);
for (bit = 7; bit >= 0; bit--) {
gpio_direction_output(pdata->gpio_clock, 0);
gpio_direction_output(pdata->gpio_data, (data >> bit) & 1);
udelay(10);
gpio_direction_output(pdata->gpio_clock, 1);
udelay(10);
}
gpio_direction_output(pdata->gpio_enable, 1);
}
static int hx8363a_panel_init(void **out_panel, struct device *dev, void *panel_pdata)
{
struct hx8363a_platform_data *pdata = panel_pdata;
struct hx8363a *panel;
int ret;
printk("%s++\n", __func__);
panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
if (!panel) {
dev_err(dev, "Failed to alloc panel data\n");
return -ENOMEM;
}
panel->pdata = pdata;
*out_panel = panel;
/* Reserve GPIO pins. */
ret = devm_gpio_request(dev, pdata->gpio_reset, "LCD panel reset");
if (ret) {
dev_err(dev,
"Failed to request LCD panel reset pin: %d\n", ret);
return ret;
}
ret = devm_gpio_request(dev, pdata->gpio_clock, "LCD 3-wire clock");
if (ret) {
dev_err(dev,
"Failed to request LCD panel 3-wire clock pin: %d\n",
ret);
return ret;
}
ret = devm_gpio_request(dev, pdata->gpio_enable, "LCD 3-wire enable");
if (ret) {
dev_err(dev,
"Failed to request LCD panel 3-wire enable pin: %d\n",
ret);
return ret;
}
ret = devm_gpio_request(dev, pdata->gpio_data, "LCD 3-wire data");
if (ret) {
dev_err(dev,
"Failed to request LCD panel 3-wire data pin: %d\n",
ret);
return ret;
}
/* Set initial GPIO pin directions and value. */
gpio_direction_output(pdata->gpio_clock, 1);
gpio_direction_output(pdata->gpio_enable, 1);
gpio_direction_output(pdata->gpio_data, 0);
printk("%s--\n", __func__);
return 0;
}
static void hx8363a_panel_exit(void *panel)
{
}
static void hx8363a_panel_enable(void *panel)
{
struct hx8363a_platform_data *pdata = ((struct hx8363a *)panel)->pdata;
printk("%s++\n", __func__);
// Reset LCD panel
gpio_direction_output(pdata->gpio_reset, 0);
mdelay(50);
gpio_direction_output(pdata->gpio_reset, 1);
mdelay(50);
hx8363a_send_cmd(pdata, 0xB9);
hx8363a_send_data(pdata, 0xFF);
hx8363a_send_data(pdata, 0x83);
hx8363a_send_data(pdata, 0x63);
// Set_POWER
hx8363a_send_cmd(pdata, 0xB1);
hx8363a_send_data(pdata, 0x81);
hx8363a_send_data(pdata, 0x30);
hx8363a_send_data(pdata, 0x08); // 0x08
hx8363a_send_data(pdata, 0x36);
hx8363a_send_data(pdata, 0x01);
hx8363a_send_data(pdata, 0x13);
hx8363a_send_data(pdata, 0x10);
hx8363a_send_data(pdata, 0x10);
hx8363a_send_data(pdata, 0x35);
hx8363a_send_data(pdata, 0x3D);
hx8363a_send_data(pdata, 0x1A);
hx8363a_send_data(pdata, 0x1A);
// Set COLMOD
hx8363a_send_cmd(pdata, 0x3A);
hx8363a_send_data(pdata, 0x60); // 0x55
hx8363a_send_cmd(pdata, 0x36);
hx8363a_send_data(pdata, 0x0b); // 0x0a
hx8363a_send_cmd(pdata, 0xC0);
hx8363a_send_data(pdata, 0x41);
hx8363a_send_data(pdata, 0x19);
hx8363a_send_cmd(pdata, 0xBF);
hx8363a_send_data(pdata, 0x00);
hx8363a_send_data(pdata, 0x10);
// Set_RGBIF
hx8363a_send_cmd(pdata, 0xB3);
hx8363a_send_data(pdata, 0x01);
// Set_CYC
hx8363a_send_cmd(pdata, 0xB4);
hx8363a_send_data(pdata, 0x01); //01
hx8363a_send_data(pdata, 0x12);
hx8363a_send_data(pdata, 0x72); //72
hx8363a_send_data(pdata, 0x12); //12
hx8363a_send_data(pdata, 0x06); //06
hx8363a_send_data(pdata, 0x03); //03
hx8363a_send_data(pdata, 0x54); //54
hx8363a_send_data(pdata, 0x03); //03
hx8363a_send_data(pdata, 0x4e); //4e
hx8363a_send_data(pdata, 0x00);
hx8363a_send_data(pdata, 0x00);
// Set_VCOM
hx8363a_send_cmd(pdata, 0xB6);
hx8363a_send_data(pdata, 0x33); //33 //27
// Set_PANEL
hx8363a_send_cmd(pdata, 0xCC);
hx8363a_send_data(pdata, 0x02); //02
mdelay(120);
// Set Gamma 2.2
hx8363a_send_cmd(pdata, 0xE0);
hx8363a_send_data(pdata, 0x01);
hx8363a_send_data(pdata, 0x07);
hx8363a_send_data(pdata, 0x4C);
hx8363a_send_data(pdata, 0xB0);
hx8363a_send_data(pdata, 0x36);
hx8363a_send_data(pdata, 0x3F);
hx8363a_send_data(pdata, 0x06);
hx8363a_send_data(pdata, 0x49);
hx8363a_send_data(pdata, 0x51);
hx8363a_send_data(pdata, 0x96);
hx8363a_send_data(pdata, 0x18);
hx8363a_send_data(pdata, 0xD8);
hx8363a_send_data(pdata, 0x18);
hx8363a_send_data(pdata, 0x50);
hx8363a_send_data(pdata, 0x13);
hx8363a_send_data(pdata, 0x01);
hx8363a_send_data(pdata, 0x07);
hx8363a_send_data(pdata, 0x4C);
hx8363a_send_data(pdata, 0xB0);
hx8363a_send_data(pdata, 0x36);
hx8363a_send_data(pdata, 0x3F);
hx8363a_send_data(pdata, 0x06);
hx8363a_send_data(pdata, 0x49);
hx8363a_send_data(pdata, 0x51);
hx8363a_send_data(pdata, 0x96);
hx8363a_send_data(pdata, 0x18);
hx8363a_send_data(pdata, 0xD8);
hx8363a_send_data(pdata, 0x18);
hx8363a_send_data(pdata, 0x50);
hx8363a_send_data(pdata, 0x13);
mdelay(150);
hx8363a_send_cmd(pdata, 0x11);
mdelay(200);
hx8363a_send_cmd(pdata, 0x29);
printk("%s--\n", __func__);
}
static void hx8363a_panel_disable(void *panel)
{
struct hx8363a_platform_data *pdata = ((struct hx8363a *)panel)->pdata;
printk("%s++\n", __func__);
hx8363a_send_cmd(pdata, 0x10);
printk("%s--\n", __func__);
}
struct panel_ops hx8363a_panel_ops = {
.init = hx8363a_panel_init,
.exit = hx8363a_panel_exit,
.enable = hx8363a_panel_enable,
.disable = hx8363a_panel_disable,
};
menuconfig

接著準備焊接PCB

固定屏的位置

接著開始跳線

美美的跳線

測試後發現無法正確顯示

重新焊接

更美的跳線

結果還是一樣無法正確顯示

無法正確顯示圖像

最後只好使用最安全的跳線方式

兩片PCB對接

終於可以顯示正確的圖像

正可視角

下可視角

右可視角

左可視角

上可視角