英制单位是一种源自英国的度量衡单位制。长度名称中,为了与公制或中国传统单位区别,多在单位前加一“英”字,或冠以口字旁称之,如:英里(英哩)、英尺(英呎)、英寸(英吋),或简称哩、呎、吋。
由于十进制的公制单位使用方便,多为各国采行,英国自1965年起立例转换成国际单位制[1],并于1995年完成了单位制的转换(但陆路交通仍以英里作为单位)。但国际上许多个别领域,仍沿用英制;例如电视机、电脑显示器、手机屏幕大小以英寸表示;航空管制上,如飞行高度、跑道长度等,多以英尺为单位。
1959年后,美式英制的中的英寸(inch)和英制中的英寸在科学应用和商业用途中统一为25.4毫米,但美式保留了有稍微不同的测量中使用的“测量英寸”。
- 1英寸(inch)= 2.54厘米(cm)
- 1英尺(foot)= 12英寸 = 30.48厘米
- 1码(yard)= 3英尺 = 91.44厘米
- 1英里(mile)= 1760码 = 1.609344千米(km)
以上的换算,两种单位制是相同的,但其中的中间单位如:链(chain,22码)和浪(furlong,220码)在英国使用较多。
如:
This specification applies to the Negative type TFT transmissive dot matrix
LCD module that is supplied by some company.This LCD module should be designed for mobile phone use.
LCD specification: Dots 540xRGBx960.
Double display structure:
TFT Module + FPC +BL
FULL 16.7M Color 4.5 inch TFT LCD size for main LCD;
One bare chip with gold bump (COG) TECH;
MIPI interface;
Structure: TFT PANNEL+IC+FPC+BL;
Transmissive Type LCD
540 dot-source and 960 dot-gate outputs;
16.7M Color can be selected by software; /* 256 * 256 * 256 = 16777216*/
White LED back light;
MIPI interface;
General specification
ITEM Standard value UNIT
LCD Type TFT Transmissive ---
Driver element a-Si TFT Active matrix
Number of Dots 540*(RGB)*960 Dots
Pixel Arrangement RGB Vertical Stripe
Active Area 55.485 *98.64 mm
Viewing Area (W*H) / mm
Viewing Direction FREE ANGLE
Module Size(W*H*T) 60.12x109.2x1.9 mm
Back Light White LED
System interface MIPI interface
The size can be calculated as follow: /* sqrt is "square root" */
size = sqrt( square(55.485) + square(98.64) ) / 25.4 = 113.174355... / 25.4 = 4.455683 = 4.5inch
dpi(dots per inch)
If the size is 4.5 inch, qHD:
dpi = sqrt(sqare(540) + square(960)) / size(inch) = 1101.45 / 4.5 = 244.767
If the size is 5.0 inch, qHD:
dpi = sqrt(sqare(540) + square(960)) / size(inch) = 1101.45 / 5.0 = 220.29
画面尺寸:一般是以对角线长度来表示,而此长度与画面长度的比率有关。像素大小:ppi来表示,意思是每英寸的像素数目,数目愈大表示像素尺寸愈小,以边长为0.264mm的像素为例,ppi=1inch/0.264mm=25.4mm/0.264mm=96.2
知道ppi和分辨率后就可以计算出来LCD的尺寸。
对比度 contrast
灰阶 gray level: 影像不只有亮与暗,而是充满了介于其间的明亮程度,为了重现我们所看到的自然影像,需要显示出不同的明亮程度,此即为灰阶。如以4bit分成16灰阶或以8bit分成256灰阶。
颜色 color : 亚像素; 色序法
色度学坐标系统: 1. Luma亮度, 即Y值; 2. chroma色度, CbCr
LCD: liquid crystal display
INIT_WORK(&mgmt->mdp_histogram_worker, mdp_hist_read_work); // work queue
case MIPI_VIDEO_PANEL: // register callback function
mipi = &mfd->panel_info.mipi;
mfd->vsync_init = mdp4_dsi_vsync_init;
mfd->vsync_show = mdp4_dsi_video_show_event;
mfd->hw_refresh = TRUE;
mfd->dma_fnc = mdp4_dsi_video_overlay;
mfd->lut_update = mdp_lut_update_lcdc;
mfd->do_histogram = mdp_do_histogram;
mfd->start_histogram = mdp_histogram_start;
mfd->stop_histogram = mdp_histogram_stop;
if (mfd->panel_info.pdest == DISPLAY_1) {
if_no = PRIMARY_INTF_SEL;
mfd->dma = &dma2_data;
} else {
if_no = EXTERNAL_INTF_SEL;
mfd->dma = &dma_e_data;
}
mdp4_display_intf_sel(if_no, DSI_VIDEO_INTF);
if (mdp_rev >= MDP_REV_40)
mfd->cursor_update = mdp_hw_cursor_sync_update;
else
mfd->cursor_update = mdp_hw_cursor_update;
break;
static int mdp_on(struct platform_device *pdev)
{
int ret = 0;
struct msm_fb_data_type *mfd;
mfd = platform_get_drvdata(pdev);
pr_debug("%s:+\n", __func__);
if (!(mfd->cont_splash_done)) {
if (mfd->panel.type == MIPI_VIDEO_PANEL)
mdp4_dsi_video_splash_done();
/* Clks are enabled in probe.
Disabling clocks now */
mdp_clk_ctrl(0);
mfd->cont_splash_done = 1;
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_on(pdev);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
if (mdp_rev >= MDP_REV_40) {
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
mdp_clk_ctrl(1);
mdp_bus_scale_restore_request();
mdp4_hw_init();
outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
if (mfd->panel.type == MIPI_CMD_PANEL) {
mdp_vsync_cfg_regs(mfd, FALSE);
mdp4_dsi_cmd_on(pdev);
} else if (mfd->panel.type == MIPI_VIDEO_PANEL) {
mdp4_dsi_video_on(pdev);
} else if (mfd->panel.type == HDMI_PANEL ||
mfd->panel.type == LCDC_PANEL ||
mfd->panel.type == LVDS_PANEL) {
mdp4_lcdc_on(pdev);
}
mdp_clk_ctrl(0);
mdp4_overlay_reset();
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
if (mdp_rev == MDP_REV_303 && mfd->panel.type == MIPI_CMD_PANEL) {
vsync_cntrl.dev = mfd->fbi->dev;
atomic_set(&vsync_cntrl.suspend, 1);
}
mdp_histogram_ctrl_all(TRUE);
if (ret == 0)
ret = panel_next_late_init(pdev);
pr_debug("%s:-\n", __func__);
return ret;
}
static int mdp_off(struct platform_device *pdev)
{
int ret = 0;
struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
pr_debug("%s:+\n", __func__);
mdp_histogram_ctrl_all(FALSE);
atomic_set(&vsync_cntrl.suspend, 1);
atomic_set(&vsync_cntrl.vsync_resume, 0);
complete_all(&vsync_cntrl.vsync_wait);
mdp_clk_ctrl(1);
ret = panel_next_early_off(pdev);
if (mfd->panel.type == MIPI_CMD_PANEL)
mdp4_dsi_cmd_off(pdev);
else if (mfd->panel.type == MIPI_VIDEO_PANEL)
mdp4_dsi_video_off(pdev);
else if (mfd->panel.type == HDMI_PANEL ||
mfd->panel.type == LCDC_PANEL ||
mfd->panel.type == LVDS_PANEL)
mdp4_lcdc_off(pdev);
else if (mfd->panel.type == WRITEBACK_PANEL)
mdp4_overlay_writeback_off(pdev);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_off(pdev);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
mdp_clk_ctrl(0);
#ifdef CONFIG_MSM_BUS_SCALING
mdp_bus_scale_update_request(0, 0);
#endif
pr_debug("%s:-\n", __func__);
return ret;
}
#define MDP_HISTOGRAM_TIMEOUT_MS 84 /*5 Frames*/
static int mdp_do_histogram(struct fb_info *info,
struct mdp_histogram_data *hist)
{
// ......
unsigned long timeout = (MDP_HISTOGRAM_TIMEOUT_MS * HZ) / 1000;
ret = wait_for_completion_killable_timeout(&mgmt->mdp_hist_comp, timeout);
// ......
}
case MSMFB_SET_LUT:
ret = copy_from_user(&cmap, argp, sizeof(cmap));
if (ret)
return ret;
mutex_lock(&msm_fb_ioctl_lut_sem);
ret = msm_fb_set_lut(&cmap, info);
mutex_unlock(&msm_fb_ioctl_lut_sem);
break;
case MSMFB_HISTOGRAM:
if (!mfd->panel_power_on)
return -EPERM;
if (!mfd->do_histogram)
return -ENODEV;
ret = copy_from_user(&hist, argp, sizeof(hist));
if (ret)
return ret;
ret = mfd->do_histogram(info, &hist);
break;
case MSMFB_HISTOGRAM_START:
if (!mfd->panel_power_on)
return -EPERM;
if (!mfd->start_histogram)
return -ENODEV;
ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
if (ret)
return ret;
ret = mfd->start_histogram(&hist_req);
break;
case MSMFB_HISTOGRAM_STOP:
if (!mfd->stop_histogram)
return -ENODEV;
ret = copy_from_user(&block, argp, sizeof(int));
if (ret)
return ret;
ret = mfd->stop_histogram(info, block);
break;
3. interrupt handler (call queue_work, then the function mdp_hist_read_work will work to read histogram)
void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt)
{
uint32 isr, mask;
char *base_addr = MDP_BASE + mgmt->base;
isr = inpdw(base_addr + MDP_HIST_INTR_STATUS_OFF);
mask = inpdw(base_addr + MDP_HIST_INTR_ENABLE_OFF);
outpdw(base_addr + MDP_HIST_INTR_CLEAR_OFF, isr);
mb();
isr &= mask;
if (isr & INTR_HIST_RESET_SEQ_DONE)
__mdp_histogram_kickoff(mgmt);
else if (isr & INTR_HIST_DONE)
queue_work(mdp_hist_wq, &mgmt->mdp_histogram_worker);
}
if (isr & INTR_DMA_P_HISTOGRAM) {
mdp4_stat.intr_histogram++;
ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_P, &mgmt);
if (!ret)
mdp_histogram_handle_isr(mgmt);
}
if (isr & INTR_DMA_S_HISTOGRAM) {
mdp4_stat.intr_histogram++;
ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_S, &mgmt);
if (!ret)
mdp_histogram_handle_isr(mgmt);
}
if (isr & INTR_VG1_HISTOGRAM) {
mdp4_stat.intr_histogram++;
ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_1, &mgmt);
if (!ret)
mdp_histogram_handle_isr(mgmt);
}
if (isr & INTR_VG2_HISTOGRAM) {
mdp4_stat.intr_histogram++;
ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_2, &mgmt);
if (!ret)
mdp_histogram_handle_isr(mgmt);
}
After the histogram data is transferred to the CABL core block, the histogram data is analyzed and a new backlight level is generated that is lower than the original backlight level. To compensate(['kɒmpenseɪt] 补偿) for the lowered backlight level, the CABL core block generates a CABL LUT for tone reproduction which makes the image brighter than the original input image. The new backlight level is passed to the backlight controller, while the CABL LUT values are sent to the hardware registers. A new image is generated using the CABL LUT and is sent to the LCD panel. Concurrently, the backlight controller sets the display backlight to its new level. When the new image generated by the CABL LUT is displayed on the LCD panel, the new backlight level (which is darker than the original level) is applied so that the final output image appears normal.
Refer to 80-NA308-1
LCD power management implementation
void __init msm8930_init_fb(void)
{
platform_device_register(&msm_fb_device);
platform_device_register(&mipi_dsi_NT35590_panel_device);
#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
platform_device_register(&wfd_panel_device);
platform_device_register(&wfd_device);
#endif
platform_device_register(&mipi_dsi_novatek_panel_device);
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
platform_device_register(&hdmi_msm_device);
#endif
platform_device_register(&mipi_dsi_toshiba_panel_device);
#ifdef CONFIG_FB_MSM_MIPI_GLOBAL_VIDEO_QHD_PT_PANEL // mipi_global panel register
platform_device_register(&mipi_dsi_global_panel_device);
#endif
msm_fb_register_device("mdp", &mdp_pdata);
msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata); // panel power and mipi io power
#ifdef CONFIG_MSM_BUS_SCALING
msm_fb_register_device("dtv", &dtv_pdata);
#endif
}
void __init msm8930_allocate_fb_region(void)
{
void *addr;
unsigned long size;
size = MSM_FB_SIZE;
addr = alloc_bootmem_align(size, 0x1000);
msm_fb_resources[0].start = __pa(addr);
msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
size, addr, __pa(addr));
}
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER // using triple buffer currently
#define MSM_FB_PRIM_BUF_SIZE \
(roundup((1920 * 1088 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
#define MSM_FB_PRIM_BUF_SIZE \
(roundup((1920 * 1088 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
static struct mipi_dsi_platform_data mipi_dsi_pdata = {
.vsync_gpio = MDP_VSYNC_GPIO,
.dsi_power_save = mipi_dsi_panel_power,
.splash_is_enabled = mipi_dsi_splash_is_enabled,
};
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
.mdp_max_clk = 200000000,
.mdp_max_bw = 2000000000,
.mdp_bw_ab_factor = 115,
.mdp_bw_ib_factor = 150,
#ifdef CONFIG_MSM_BUS_SCALING // 1
.mdp_bus_scale_table = &mdp_bus_scale_pdata, // ui / video720p/1080p / vga bus scale vectors
#endif
.mdp_rev = MDP_REV_43,
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION // 1
.mem_hid = BIT(ION_CP_MM_HEAP_ID),
#else
.mem_hid = MEMTYPE_EBI1,
#endif
.cont_splash_enabled = 0x01,
.mdp_iommu_split_domain = 0,
};
上电时调用mipi_dsi_panel_power
mipi_dsi_on -> mipi_dsi_panel_power(1);
mipi_dsi_off -> mipi_dsi_panel_power(0);
#define DISP_RST_GPIO 58
static int mipi_dsi_cdp_panel_power(int on)
{
/* keep the power supply of L9 and LVS2 except L2. */
static struct regulator *lcd_ic_vdd, *lcd_ic_vio, *host_mipi_vioa;
/* Control backlight GPIO (24) directly when using PM8917 */
int gpio24 = PM8917_GPIO_PM_TO_SYS(24);
int rc;
pr_debug("%s: state : %d\n", __func__, on);
if (!dsi_power_on) {
lcd_ic_vdd = regulator_get(&msm_mipi_dsi1_device.dev,
"dsi_vdc");
if (IS_ERR(lcd_ic_vdd)) {
pr_err("could not get lcd_ic_vdd, rc = %ld\n",
PTR_ERR(lcd_ic_vdd));
return -ENODEV;
}
lcd_ic_vio = regulator_get(&msm_mipi_dsi1_device.dev,
"dsi_vddio");
if (IS_ERR(lcd_ic_vio)) {
pr_err("could not get lcd_ic_vio, rc = %ld\n",
PTR_ERR(lcd_ic_vio));
return -ENODEV;
}
host_mipi_vioa = regulator_get(&msm_mipi_dsi1_device.dev,
"dsi_vdda");
if (IS_ERR(host_mipi_vioa)) {
pr_err("could not get host_mipi_vioa, rc = %ld\n",
PTR_ERR(host_mipi_vioa));
return -ENODEV;
}
rc = regulator_set_voltage(lcd_ic_vdd, 2800000, 3000000);
if (rc) {
pr_err("set_voltage lcd_ic_vdd failed, rc=%d\n", rc);
return -EINVAL;
}
if (regulator_count_voltages(lcd_ic_vio) > 0) {
rc = regulator_set_voltage(lcd_ic_vio, 1800000, 1800000);
if (rc) {
pr_err("set_voltage lcd_ic_vio failed, rc=%d\n", rc);
return -EINVAL;
}
}
rc = regulator_set_voltage(host_mipi_vioa, 1200000, 1200000);
if (rc) {
pr_err("set_voltage host_mipi_vioa failed, rc=%d\n", rc);
return -EINVAL;
}
rc = regulator_set_optimum_mode(lcd_ic_vdd, 100000);
if (rc < 0) {
pr_err("set_optimum_mode lcd_ic_vdd failed, rc=%d\n", rc);
return -EINVAL;
}
rc = regulator_set_optimum_mode(lcd_ic_vio, 100000);
if (rc < 0) {
pr_err("set_optimum_mode lcd_ic_vio failed, rc=%d\n", rc);
return -EINVAL;
}
rc = regulator_enable(lcd_ic_vdd);
if (rc) {
pr_err("enable lcd_ic_vdd failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_enable(lcd_ic_vio);
if (rc) {
pr_err("enable lcd_ic_vio failed, rc=%d\n", rc);
return -ENODEV;
}
rc = gpio_request(DISP_RST_GPIO, "disp_rst_n");
if (rc) {
pr_err("request gpio DISP_RST_GPIO failed, rc=%d\n",
rc);
gpio_free(DISP_RST_GPIO);
return -ENODEV;
}
if (machine_is_msm8930_evt()) {
rc = gpio_direction_output(DISP_RST_GPIO, 1);
if (rc) {
pr_err("gpio_direction_output failed for %d gpio rc=%d\n",
DISP_RST_GPIO, rc);
return -ENODEV;
}
}
if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
rc = gpio_request(gpio24, "disp_bl");
if (rc) {
pr_err("request for gpio 24 failed, rc=%d\n",
rc);
return -ENODEV;
}
gpio_set_value_cansleep(gpio24, 0);
novatek_pdata.gpio_set_backlight =
pm8917_gpio_set_backlight;
}
dsi_power_on = true;
}
if (on) {
rc = regulator_set_optimum_mode(host_mipi_vioa, 100000);
if (rc < 0) {
pr_err("set_optimum_mode host_mipi_vioa failed, rc=%d\n", rc);
return -EINVAL;
}
rc = regulator_enable(host_mipi_vioa);
if (rc) {
pr_err("enable host_mipi_vioa failed, rc=%d\n", rc);
return -ENODEV;
}
/* Reset lcd driver ic */
gpio_set_value(DISP_RST_GPIO, 1);
msleep(1);
gpio_set_value(DISP_RST_GPIO, 0);
msleep(2);
gpio_set_value(DISP_RST_GPIO, 1);
msleep(20);
} else {
rc = regulator_disable(host_mipi_vioa);
if (rc) {
pr_err("disable host_mipi_vioa failed, rc=%d\n", rc);
return -ENODEV;
}
rc = regulator_set_optimum_mode(host_mipi_vioa, 100);
if (rc < 0) {
pr_err("set_optimum_mode host_mipi_vioa failed, rc=%d\n", rc);
return -EINVAL;
}
}
return 0;
}
board-8930-regulator-pm8038.c
VREG_CONSUMERS(L2) = { // 150mA 1V2_VREG_L2
REGULATOR_SUPPLY("8038_l2", NULL),
REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"), // host mipi voltage io analog 1.2V, msm-8930 pwr, pin: VDD_MIPI_1/2/3
REGULATOR_SUPPLY("dsi_pll_vdda", "mdp.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
};
VREG_CONSUMERS(L9) = { // 300mA 2V85_VREG_L9
REGULATOR_SUPPLY("8038_l9", NULL),
REGULATOR_SUPPLY("vdd_ana", "3-004a"),
REGULATOR_SUPPLY("vdd_ana", "3-0038"),
REGULATOR_SUPPLY("vdd_ana", "3-0020"),
REGULATOR_SUPPLY("vdd", "3-0024"),
/* Regulators for 8930 QRD SGLTE EVT */
REGULATOR_SUPPLY("cam_vana", "8-001a"),
REGULATOR_SUPPLY("cam_vana", "8-006c"),
REGULATOR_SUPPLY("cam_vana", "8-0048"),
REGULATOR_SUPPLY("cam_vana", "8-0020"),
REGULATOR_SUPPLY("cam_vana", "8-0036"),
REGULATOR_SUPPLY("cam_vana", "8-0010"),
REGULATOR_SUPPLY("cam_vaf", "8-001a"),
REGULATOR_SUPPLY("cam_vaf", "8-006c"),
REGULATOR_SUPPLY("cam_vaf", "8-0048"),
REGULATOR_SUPPLY("cam_vaf", "8-0020"),
REGULATOR_SUPPLY("cam_vaf", "8-0036"),
REGULATOR_SUPPLY("cam_vaf", "8-0010"),
REGULATOR_SUPPLY("vdd", "12-0018"),
REGULATOR_SUPPLY("vdd", "12-0068"),
REGULATOR_SUPPLY("dsi_vdc", "mipi_dsi.1"), // lcd driver ic power supply 2.85V
};
VREG_L11: read lcd id using ADC, power supply 1.8V 600mA
VREG_CONSUMERS(LVS2) = { // 100mA 1V8_VREG_LVS2
REGULATOR_SUPPLY("8038_lvs2", NULL),
REGULATOR_SUPPLY("vcc_i2c", "3-004a"),
REGULATOR_SUPPLY("vcc_i2c", "3-0038"),
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
REGULATOR_SUPPLY("vcc_i2c", "3-0020"),
REGULATOR_SUPPLY("vcc_i2c", "0-0048"),
REGULATOR_SUPPLY("vddio", "12-0018"),
REGULATOR_SUPPLY("vlogic", "12-0068"),
REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"), // lcd driver ic voltage io 1.8V
};