brintos

brintos / linux-shallow public Read only

0
0
Text · 17.3 KiB · df746ba Raw
917 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd4 *5 * Author: Jerry Han <jerry.han.hq@gmail.com>6 *7 */8 9#include <linux/delay.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/of.h>13 14#include <linux/gpio/consumer.h>15#include <linux/regulator/consumer.h>16 17#include <drm/drm_device.h>18#include <drm/drm_mipi_dsi.h>19#include <drm/drm_modes.h>20#include <drm/drm_panel.h>21 22#include <video/mipi_display.h>23 24struct panel_cmd {25	char cmd;26	char data;27};28 29struct panel_desc {30	const struct drm_display_mode *display_mode;31	unsigned int bpc;32	unsigned int width_mm;33	unsigned int height_mm;34 35	unsigned long mode_flags;36	enum mipi_dsi_pixel_format format;37	unsigned int lanes;38	const struct panel_cmd *on_cmds;39	unsigned int on_cmds_num;40};41 42struct panel_info {43	struct drm_panel base;44	struct mipi_dsi_device *link;45	const struct panel_desc *desc;46 47	struct gpio_desc *enable_gpio;48	struct gpio_desc *pp33_gpio;49	struct gpio_desc *pp18_gpio;50};51 52static inline struct panel_info *to_panel_info(struct drm_panel *panel)53{54	return container_of(panel, struct panel_info, base);55}56 57static void disable_gpios(struct panel_info *pinfo)58{59	gpiod_set_value(pinfo->enable_gpio, 0);60	gpiod_set_value(pinfo->pp33_gpio, 0);61	gpiod_set_value(pinfo->pp18_gpio, 0);62}63 64static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds)65{66	struct panel_info *pinfo = to_panel_info(panel);67	unsigned int i = 0;68	int err;69 70	for (i = 0; i < pinfo->desc->on_cmds_num; i++) {71		err = mipi_dsi_dcs_write_buffer(pinfo->link, &cmds[i],72						sizeof(struct panel_cmd));73 74		if (err < 0)75			return err;76	}77 78	return 0;79}80 81static int boe_panel_disable(struct drm_panel *panel)82{83	struct panel_info *pinfo = to_panel_info(panel);84	int err;85 86	err = mipi_dsi_dcs_set_display_off(pinfo->link);87	if (err < 0) {88		dev_err(panel->dev, "failed to set display off: %d\n", err);89		return err;90	}91 92	return 0;93}94 95static int boe_panel_unprepare(struct drm_panel *panel)96{97	struct panel_info *pinfo = to_panel_info(panel);98	int err;99 100	err = mipi_dsi_dcs_set_display_off(pinfo->link);101	if (err < 0)102		dev_err(panel->dev, "failed to set display off: %d\n", err);103 104	err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);105	if (err < 0)106		dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);107 108	/* sleep_mode_delay: 1ms - 2ms */109	usleep_range(1000, 2000);110 111	disable_gpios(pinfo);112 113	return 0;114}115 116static int boe_panel_prepare(struct drm_panel *panel)117{118	struct panel_info *pinfo = to_panel_info(panel);119	int err;120 121	gpiod_set_value(pinfo->pp18_gpio, 1);122	/* T1: 5ms - 6ms */123	usleep_range(5000, 6000);124	gpiod_set_value(pinfo->pp33_gpio, 1);125 126	/* reset sequence */127	/* T2: 14ms - 15ms */128	usleep_range(14000, 15000);129	gpiod_set_value(pinfo->enable_gpio, 1);130 131	/* T3: 1ms - 2ms */132	usleep_range(1000, 2000);133	gpiod_set_value(pinfo->enable_gpio, 0);134 135	/* T4: 1ms - 2ms */136	usleep_range(1000, 2000);137	gpiod_set_value(pinfo->enable_gpio, 1);138 139	/* T5: 5ms - 6ms */140	usleep_range(5000, 6000);141 142	/* send init code */143	err = send_mipi_cmds(panel, pinfo->desc->on_cmds);144	if (err < 0) {145		dev_err(panel->dev, "failed to send DCS Init Code: %d\n", err);146		goto poweroff;147	}148 149	err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);150	if (err < 0) {151		dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);152		goto poweroff;153	}154 155	/* T6: 120ms - 121ms */156	usleep_range(120000, 121000);157 158	err = mipi_dsi_dcs_set_display_on(pinfo->link);159	if (err < 0) {160		dev_err(panel->dev, "failed to set display on: %d\n", err);161		goto poweroff;162	}163 164	/* T7: 20ms - 21ms */165	usleep_range(20000, 21000);166 167	return 0;168 169poweroff:170	disable_gpios(pinfo);171	return err;172}173 174static int boe_panel_enable(struct drm_panel *panel)175{176	struct panel_info *pinfo = to_panel_info(panel);177	int ret;178 179	usleep_range(120000, 121000);180 181	ret = mipi_dsi_dcs_set_display_on(pinfo->link);182	if (ret < 0) {183		dev_err(panel->dev, "failed to set display on: %d\n", ret);184		return ret;185	}186 187	return 0;188}189 190static int boe_panel_get_modes(struct drm_panel *panel,191			       struct drm_connector *connector)192{193	struct panel_info *pinfo = to_panel_info(panel);194	const struct drm_display_mode *m = pinfo->desc->display_mode;195	struct drm_display_mode *mode;196 197	mode = drm_mode_duplicate(connector->dev, m);198	if (!mode) {199		dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n",200			m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));201		return -ENOMEM;202	}203 204	drm_mode_set_name(mode);205 206	drm_mode_probed_add(connector, mode);207 208	connector->display_info.width_mm = pinfo->desc->width_mm;209	connector->display_info.height_mm = pinfo->desc->height_mm;210	connector->display_info.bpc = pinfo->desc->bpc;211 212	return 1;213}214 215static const struct drm_panel_funcs panel_funcs = {216	.disable = boe_panel_disable,217	.unprepare = boe_panel_unprepare,218	.prepare = boe_panel_prepare,219	.enable = boe_panel_enable,220	.get_modes = boe_panel_get_modes,221};222 223static const struct drm_display_mode default_display_mode = {224	.clock = 159420,225	.hdisplay = 1200,226	.hsync_start = 1200 + 80,227	.hsync_end = 1200 + 80 + 60,228	.htotal = 1200 + 80 + 60 + 24,229	.vdisplay = 1920,230	.vsync_start = 1920 + 10,231	.vsync_end = 1920 + 10 + 14,232	.vtotal = 1920 + 10 + 14 + 4,233};234 235/* 8 inch */236static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {237	{ 0xB0, 0x05 },238	{ 0xB1, 0xE5 },239	{ 0xB3, 0x52 },240	{ 0xC0, 0x00 },241	{ 0xC2, 0x57 },242	{ 0xD9, 0x85 },243	{ 0xB0, 0x01 },244	{ 0xC8, 0x00 },245	{ 0xC9, 0x00 },246	{ 0xCC, 0x26 },247	{ 0xCD, 0x26 },248	{ 0xDC, 0x00 },249	{ 0xDD, 0x00 },250	{ 0xE0, 0x26 },251	{ 0xE1, 0x26 },252	{ 0xB0, 0x03 },253	{ 0xC3, 0x2A },254	{ 0xE7, 0x2A },255	{ 0xC5, 0x2A },256	{ 0xDE, 0x2A },257	{ 0xBC, 0x02 },258	{ 0xCB, 0x02 },259	{ 0xB0, 0x00 },260	{ 0xB6, 0x03 },261	{ 0xBA, 0x8B },262	{ 0xBF, 0x15 },263	{ 0xC0, 0x18 },264	{ 0xC2, 0x14 },265	{ 0xC3, 0x02 },266	{ 0xC4, 0x14 },267	{ 0xC5, 0x02 },268	{ 0xCC, 0x0A },269	{ 0xB0, 0x06 },270	{ 0xC0, 0xA5 },271	{ 0xD5, 0x20 },272	{ 0xC0, 0x00 },273	{ 0xB0, 0x02 },274	{ 0xC0, 0x00 },275	{ 0xC1, 0x02 },276	{ 0xC2, 0x06 },277	{ 0xC3, 0x16 },278	{ 0xC4, 0x0E },279	{ 0xC5, 0x18 },280	{ 0xC6, 0x26 },281	{ 0xC7, 0x32 },282	{ 0xC8, 0x3F },283	{ 0xC9, 0x3F },284	{ 0xCA, 0x3F },285	{ 0xCB, 0x3F },286	{ 0xCC, 0x3D },287	{ 0xCD, 0x2F },288	{ 0xCE, 0x2F },289	{ 0xCF, 0x2F },290	{ 0xD0, 0x07 },291	{ 0xD2, 0x00 },292	{ 0xD3, 0x02 },293	{ 0xD4, 0x06 },294	{ 0xD5, 0x12 },295	{ 0xD6, 0x0A },296	{ 0xD7, 0x14 },297	{ 0xD8, 0x22 },298	{ 0xD9, 0x2E },299	{ 0xDA, 0x3D },300	{ 0xDB, 0x3F },301	{ 0xDC, 0x3F },302	{ 0xDD, 0x3F },303	{ 0xDE, 0x3D },304	{ 0xDF, 0x2F },305	{ 0xE0, 0x2F },306	{ 0xE1, 0x2F },307	{ 0xE2, 0x07 },308	{ 0xB0, 0x07 },309	{ 0xB1, 0x18 },310	{ 0xB2, 0x19 },311	{ 0xB3, 0x2E },312	{ 0xB4, 0x52 },313	{ 0xB5, 0x72 },314	{ 0xB6, 0x8C },315	{ 0xB7, 0xBD },316	{ 0xB8, 0xEB },317	{ 0xB9, 0x47 },318	{ 0xBA, 0x96 },319	{ 0xBB, 0x1E },320	{ 0xBC, 0x90 },321	{ 0xBD, 0x93 },322	{ 0xBE, 0xFA },323	{ 0xBF, 0x56 },324	{ 0xC0, 0x8C },325	{ 0xC1, 0xB7 },326	{ 0xC2, 0xCC },327	{ 0xC3, 0xDF },328	{ 0xC4, 0xE8 },329	{ 0xC5, 0xF0 },330	{ 0xC6, 0xF8 },331	{ 0xC7, 0xFA },332	{ 0xC8, 0xFC },333	{ 0xC9, 0x00 },334	{ 0xCA, 0x00 },335	{ 0xCB, 0x5A },336	{ 0xCC, 0xAF },337	{ 0xCD, 0xFF },338	{ 0xCE, 0xFF },339	{ 0xB0, 0x08 },340	{ 0xB1, 0x04 },341	{ 0xB2, 0x15 },342	{ 0xB3, 0x2D },343	{ 0xB4, 0x51 },344	{ 0xB5, 0x72 },345	{ 0xB6, 0x8D },346	{ 0xB7, 0xBE },347	{ 0xB8, 0xED },348	{ 0xB9, 0x4A },349	{ 0xBA, 0x9A },350	{ 0xBB, 0x23 },351	{ 0xBC, 0x95 },352	{ 0xBD, 0x98 },353	{ 0xBE, 0xFF },354	{ 0xBF, 0x59 },355	{ 0xC0, 0x8E },356	{ 0xC1, 0xB9 },357	{ 0xC2, 0xCD },358	{ 0xC3, 0xDF },359	{ 0xC4, 0xE8 },360	{ 0xC5, 0xF0 },361	{ 0xC6, 0xF8 },362	{ 0xC7, 0xFA },363	{ 0xC8, 0xFC },364	{ 0xC9, 0x00 },365	{ 0xCA, 0x00 },366	{ 0xCB, 0x5A },367	{ 0xCC, 0xAF },368	{ 0xCD, 0xFF },369	{ 0xCE, 0xFF },370	{ 0xB0, 0x09 },371	{ 0xB1, 0x04 },372	{ 0xB2, 0x2C },373	{ 0xB3, 0x36 },374	{ 0xB4, 0x53 },375	{ 0xB5, 0x73 },376	{ 0xB6, 0x8E },377	{ 0xB7, 0xC0 },378	{ 0xB8, 0xEF },379	{ 0xB9, 0x4C },380	{ 0xBA, 0x9D },381	{ 0xBB, 0x25 },382	{ 0xBC, 0x96 },383	{ 0xBD, 0x9A },384	{ 0xBE, 0x01 },385	{ 0xBF, 0x59 },386	{ 0xC0, 0x8E },387	{ 0xC1, 0xB9 },388	{ 0xC2, 0xCD },389	{ 0xC3, 0xDF },390	{ 0xC4, 0xE8 },391	{ 0xC5, 0xF0 },392	{ 0xC6, 0xF8 },393	{ 0xC7, 0xFA },394	{ 0xC8, 0xFC },395	{ 0xC9, 0x00 },396	{ 0xCA, 0x00 },397	{ 0xCB, 0x5A },398	{ 0xCC, 0xBF },399	{ 0xCD, 0xFF },400	{ 0xCE, 0xFF },401	{ 0xB0, 0x0A },402	{ 0xB1, 0x18 },403	{ 0xB2, 0x19 },404	{ 0xB3, 0x2E },405	{ 0xB4, 0x52 },406	{ 0xB5, 0x72 },407	{ 0xB6, 0x8C },408	{ 0xB7, 0xBD },409	{ 0xB8, 0xEB },410	{ 0xB9, 0x47 },411	{ 0xBA, 0x96 },412	{ 0xBB, 0x1E },413	{ 0xBC, 0x90 },414	{ 0xBD, 0x93 },415	{ 0xBE, 0xFA },416	{ 0xBF, 0x56 },417	{ 0xC0, 0x8C },418	{ 0xC1, 0xB7 },419	{ 0xC2, 0xCC },420	{ 0xC3, 0xDF },421	{ 0xC4, 0xE8 },422	{ 0xC5, 0xF0 },423	{ 0xC6, 0xF8 },424	{ 0xC7, 0xFA },425	{ 0xC8, 0xFC },426	{ 0xC9, 0x00 },427	{ 0xCA, 0x00 },428	{ 0xCB, 0x5A },429	{ 0xCC, 0xAF },430	{ 0xCD, 0xFF },431	{ 0xCE, 0xFF },432	{ 0xB0, 0x0B },433	{ 0xB1, 0x04 },434	{ 0xB2, 0x15 },435	{ 0xB3, 0x2D },436	{ 0xB4, 0x51 },437	{ 0xB5, 0x72 },438	{ 0xB6, 0x8D },439	{ 0xB7, 0xBE },440	{ 0xB8, 0xED },441	{ 0xB9, 0x4A },442	{ 0xBA, 0x9A },443	{ 0xBB, 0x23 },444	{ 0xBC, 0x95 },445	{ 0xBD, 0x98 },446	{ 0xBE, 0xFF },447	{ 0xBF, 0x59 },448	{ 0xC0, 0x8E },449	{ 0xC1, 0xB9 },450	{ 0xC2, 0xCD },451	{ 0xC3, 0xDF },452	{ 0xC4, 0xE8 },453	{ 0xC5, 0xF0 },454	{ 0xC6, 0xF8 },455	{ 0xC7, 0xFA },456	{ 0xC8, 0xFC },457	{ 0xC9, 0x00 },458	{ 0xCA, 0x00 },459	{ 0xCB, 0x5A },460	{ 0xCC, 0xAF },461	{ 0xCD, 0xFF },462	{ 0xCE, 0xFF },463	{ 0xB0, 0x0C },464	{ 0xB1, 0x04 },465	{ 0xB2, 0x2C },466	{ 0xB3, 0x36 },467	{ 0xB4, 0x53 },468	{ 0xB5, 0x73 },469	{ 0xB6, 0x8E },470	{ 0xB7, 0xC0 },471	{ 0xB8, 0xEF },472	{ 0xB9, 0x4C },473	{ 0xBA, 0x9D },474	{ 0xBB, 0x25 },475	{ 0xBC, 0x96 },476	{ 0xBD, 0x9A },477	{ 0xBE, 0x01 },478	{ 0xBF, 0x59 },479	{ 0xC0, 0x8E },480	{ 0xC1, 0xB9 },481	{ 0xC2, 0xCD },482	{ 0xC3, 0xDF },483	{ 0xC4, 0xE8 },484	{ 0xC5, 0xF0 },485	{ 0xC6, 0xF8 },486	{ 0xC7, 0xFA },487	{ 0xC8, 0xFC },488	{ 0xC9, 0x00 },489	{ 0xCA, 0x00 },490	{ 0xCB, 0x5A },491	{ 0xCC, 0xBF },492	{ 0xCD, 0xFF },493	{ 0xCE, 0xFF },494	{ 0xB0, 0x04 },495	{ 0xB5, 0x02 },496	{ 0xB6, 0x01 },497};498 499static const struct panel_desc boe_himax8279d8p_panel_desc = {500	.display_mode = &default_display_mode,501	.bpc = 8,502	.width_mm = 107,503	.height_mm = 172,504	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |505			MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,506	.format = MIPI_DSI_FMT_RGB888,507	.lanes = 4,508	.on_cmds = boe_himax8279d8p_on_cmds,509	.on_cmds_num = 260,510};511 512/* 10 inch */513static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {514	{ 0xB0, 0x05 },515	{ 0xB1, 0xE5 },516	{ 0xB3, 0x52 },517	{ 0xB0, 0x00 },518	{ 0xB6, 0x03 },519	{ 0xBA, 0x8B },520	{ 0xBF, 0x1A },521	{ 0xC0, 0x0F },522	{ 0xC2, 0x0C },523	{ 0xC3, 0x02 },524	{ 0xC4, 0x0C },525	{ 0xC5, 0x02 },526	{ 0xB0, 0x01 },527	{ 0xE0, 0x26 },528	{ 0xE1, 0x26 },529	{ 0xDC, 0x00 },530	{ 0xDD, 0x00 },531	{ 0xCC, 0x26 },532	{ 0xCD, 0x26 },533	{ 0xC8, 0x00 },534	{ 0xC9, 0x00 },535	{ 0xD2, 0x03 },536	{ 0xD3, 0x03 },537	{ 0xE6, 0x04 },538	{ 0xE7, 0x04 },539	{ 0xC4, 0x09 },540	{ 0xC5, 0x09 },541	{ 0xD8, 0x0A },542	{ 0xD9, 0x0A },543	{ 0xC2, 0x0B },544	{ 0xC3, 0x0B },545	{ 0xD6, 0x0C },546	{ 0xD7, 0x0C },547	{ 0xC0, 0x05 },548	{ 0xC1, 0x05 },549	{ 0xD4, 0x06 },550	{ 0xD5, 0x06 },551	{ 0xCA, 0x07 },552	{ 0xCB, 0x07 },553	{ 0xDE, 0x08 },554	{ 0xDF, 0x08 },555	{ 0xB0, 0x02 },556	{ 0xC0, 0x00 },557	{ 0xC1, 0x0D },558	{ 0xC2, 0x17 },559	{ 0xC3, 0x26 },560	{ 0xC4, 0x31 },561	{ 0xC5, 0x1C },562	{ 0xC6, 0x2C },563	{ 0xC7, 0x33 },564	{ 0xC8, 0x31 },565	{ 0xC9, 0x37 },566	{ 0xCA, 0x37 },567	{ 0xCB, 0x37 },568	{ 0xCC, 0x39 },569	{ 0xCD, 0x2E },570	{ 0xCE, 0x2F },571	{ 0xCF, 0x2F },572	{ 0xD0, 0x07 },573	{ 0xD2, 0x00 },574	{ 0xD3, 0x0D },575	{ 0xD4, 0x17 },576	{ 0xD5, 0x26 },577	{ 0xD6, 0x31 },578	{ 0xD7, 0x3F },579	{ 0xD8, 0x3F },580	{ 0xD9, 0x3F },581	{ 0xDA, 0x3F },582	{ 0xDB, 0x37 },583	{ 0xDC, 0x37 },584	{ 0xDD, 0x37 },585	{ 0xDE, 0x39 },586	{ 0xDF, 0x2E },587	{ 0xE0, 0x2F },588	{ 0xE1, 0x2F },589	{ 0xE2, 0x07 },590	{ 0xB0, 0x03 },591	{ 0xC8, 0x0B },592	{ 0xC9, 0x07 },593	{ 0xC3, 0x00 },594	{ 0xE7, 0x00 },595	{ 0xC5, 0x2A },596	{ 0xDE, 0x2A },597	{ 0xCA, 0x43 },598	{ 0xC9, 0x07 },599	{ 0xE4, 0xC0 },600	{ 0xE5, 0x0D },601	{ 0xCB, 0x01 },602	{ 0xBC, 0x01 },603	{ 0xB0, 0x06 },604	{ 0xB8, 0xA5 },605	{ 0xC0, 0xA5 },606	{ 0xC7, 0x0F },607	{ 0xD5, 0x32 },608	{ 0xB8, 0x00 },609	{ 0xC0, 0x00 },610	{ 0xBC, 0x00 },611	{ 0xB0, 0x07 },612	{ 0xB1, 0x00 },613	{ 0xB2, 0x05 },614	{ 0xB3, 0x10 },615	{ 0xB4, 0x22 },616	{ 0xB5, 0x36 },617	{ 0xB6, 0x4A },618	{ 0xB7, 0x6C },619	{ 0xB8, 0x9A },620	{ 0xB9, 0xD7 },621	{ 0xBA, 0x17 },622	{ 0xBB, 0x92 },623	{ 0xBC, 0x15 },624	{ 0xBD, 0x18 },625	{ 0xBE, 0x8C },626	{ 0xBF, 0x00 },627	{ 0xC0, 0x3A },628	{ 0xC1, 0x72 },629	{ 0xC2, 0x8C },630	{ 0xC3, 0xA5 },631	{ 0xC4, 0xB1 },632	{ 0xC5, 0xBE },633	{ 0xC6, 0xCA },634	{ 0xC7, 0xD1 },635	{ 0xC8, 0xD4 },636	{ 0xC9, 0x00 },637	{ 0xCA, 0x00 },638	{ 0xCB, 0x16 },639	{ 0xCC, 0xAF },640	{ 0xCD, 0xFF },641	{ 0xCE, 0xFF },642	{ 0xB0, 0x08 },643	{ 0xB1, 0x04 },644	{ 0xB2, 0x05 },645	{ 0xB3, 0x11 },646	{ 0xB4, 0x24 },647	{ 0xB5, 0x39 },648	{ 0xB6, 0x4E },649	{ 0xB7, 0x72 },650	{ 0xB8, 0xA3 },651	{ 0xB9, 0xE1 },652	{ 0xBA, 0x25 },653	{ 0xBB, 0xA8 },654	{ 0xBC, 0x2E },655	{ 0xBD, 0x32 },656	{ 0xBE, 0xAD },657	{ 0xBF, 0x28 },658	{ 0xC0, 0x63 },659	{ 0xC1, 0x9B },660	{ 0xC2, 0xB5 },661	{ 0xC3, 0xCF },662	{ 0xC4, 0xDB },663	{ 0xC5, 0xE8 },664	{ 0xC6, 0xF5 },665	{ 0xC7, 0xFA },666	{ 0xC8, 0xFC },667	{ 0xC9, 0x00 },668	{ 0xCA, 0x00 },669	{ 0xCB, 0x16 },670	{ 0xCC, 0xAF },671	{ 0xCD, 0xFF },672	{ 0xCE, 0xFF },673	{ 0xB0, 0x09 },674	{ 0xB1, 0x04 },675	{ 0xB2, 0x04 },676	{ 0xB3, 0x0F },677	{ 0xB4, 0x22 },678	{ 0xB5, 0x37 },679	{ 0xB6, 0x4D },680	{ 0xB7, 0x71 },681	{ 0xB8, 0xA2 },682	{ 0xB9, 0xE1 },683	{ 0xBA, 0x26 },684	{ 0xBB, 0xA9 },685	{ 0xBC, 0x2F },686	{ 0xBD, 0x33 },687	{ 0xBE, 0xAC },688	{ 0xBF, 0x24 },689	{ 0xC0, 0x5D },690	{ 0xC1, 0x94 },691	{ 0xC2, 0xAC },692	{ 0xC3, 0xC5 },693	{ 0xC4, 0xD1 },694	{ 0xC5, 0xDC },695	{ 0xC6, 0xE8 },696	{ 0xC7, 0xED },697	{ 0xC8, 0xF0 },698	{ 0xC9, 0x00 },699	{ 0xCA, 0x00 },700	{ 0xCB, 0x16 },701	{ 0xCC, 0xAF },702	{ 0xCD, 0xFF },703	{ 0xCE, 0xFF },704	{ 0xB0, 0x0A },705	{ 0xB1, 0x00 },706	{ 0xB2, 0x05 },707	{ 0xB3, 0x10 },708	{ 0xB4, 0x22 },709	{ 0xB5, 0x36 },710	{ 0xB6, 0x4A },711	{ 0xB7, 0x6C },712	{ 0xB8, 0x9A },713	{ 0xB9, 0xD7 },714	{ 0xBA, 0x17 },715	{ 0xBB, 0x92 },716	{ 0xBC, 0x15 },717	{ 0xBD, 0x18 },718	{ 0xBE, 0x8C },719	{ 0xBF, 0x00 },720	{ 0xC0, 0x3A },721	{ 0xC1, 0x72 },722	{ 0xC2, 0x8C },723	{ 0xC3, 0xA5 },724	{ 0xC4, 0xB1 },725	{ 0xC5, 0xBE },726	{ 0xC6, 0xCA },727	{ 0xC7, 0xD1 },728	{ 0xC8, 0xD4 },729	{ 0xC9, 0x00 },730	{ 0xCA, 0x00 },731	{ 0xCB, 0x16 },732	{ 0xCC, 0xAF },733	{ 0xCD, 0xFF },734	{ 0xCE, 0xFF },735	{ 0xB0, 0x0B },736	{ 0xB1, 0x04 },737	{ 0xB2, 0x05 },738	{ 0xB3, 0x11 },739	{ 0xB4, 0x24 },740	{ 0xB5, 0x39 },741	{ 0xB6, 0x4E },742	{ 0xB7, 0x72 },743	{ 0xB8, 0xA3 },744	{ 0xB9, 0xE1 },745	{ 0xBA, 0x25 },746	{ 0xBB, 0xA8 },747	{ 0xBC, 0x2E },748	{ 0xBD, 0x32 },749	{ 0xBE, 0xAD },750	{ 0xBF, 0x28 },751	{ 0xC0, 0x63 },752	{ 0xC1, 0x9B },753	{ 0xC2, 0xB5 },754	{ 0xC3, 0xCF },755	{ 0xC4, 0xDB },756	{ 0xC5, 0xE8 },757	{ 0xC6, 0xF5 },758	{ 0xC7, 0xFA },759	{ 0xC8, 0xFC },760	{ 0xC9, 0x00 },761	{ 0xCA, 0x00 },762	{ 0xCB, 0x16 },763	{ 0xCC, 0xAF },764	{ 0xCD, 0xFF },765	{ 0xCE, 0xFF },766	{ 0xB0, 0x0C },767	{ 0xB1, 0x04 },768	{ 0xB2, 0x04 },769	{ 0xB3, 0x0F },770	{ 0xB4, 0x22 },771	{ 0xB5, 0x37 },772	{ 0xB6, 0x4D },773	{ 0xB7, 0x71 },774	{ 0xB8, 0xA2 },775	{ 0xB9, 0xE1 },776	{ 0xBA, 0x26 },777	{ 0xBB, 0xA9 },778	{ 0xBC, 0x2F },779	{ 0xBD, 0x33 },780	{ 0xBE, 0xAC },781	{ 0xBF, 0x24 },782	{ 0xC0, 0x5D },783	{ 0xC1, 0x94 },784	{ 0xC2, 0xAC },785	{ 0xC3, 0xC5 },786	{ 0xC4, 0xD1 },787	{ 0xC5, 0xDC },788	{ 0xC6, 0xE8 },789	{ 0xC7, 0xED },790	{ 0xC8, 0xF0 },791	{ 0xC9, 0x00 },792	{ 0xCA, 0x00 },793	{ 0xCB, 0x16 },794	{ 0xCC, 0xAF },795	{ 0xCD, 0xFF },796	{ 0xCE, 0xFF },797};798 799static const struct panel_desc boe_himax8279d10p_panel_desc = {800	.display_mode = &default_display_mode,801	.bpc = 8,802	.width_mm = 135,803	.height_mm = 216,804	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |805			MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,806	.format = MIPI_DSI_FMT_RGB888,807	.lanes = 4,808	.on_cmds = boe_himax8279d10p_on_cmds,809	.on_cmds_num = 283,810};811 812static const struct of_device_id panel_of_match[] = {813	{814		.compatible = "boe,himax8279d8p",815		.data = &boe_himax8279d8p_panel_desc,816	},817	{818		.compatible = "boe,himax8279d10p",819		.data = &boe_himax8279d10p_panel_desc,820	},821	{822		/* sentinel */823	}824};825MODULE_DEVICE_TABLE(of, panel_of_match);826 827static int panel_add(struct panel_info *pinfo)828{829	struct device *dev = &pinfo->link->dev;830	int ret;831 832	pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH);833	if (IS_ERR(pinfo->pp18_gpio)) {834		return dev_err_probe(dev, PTR_ERR(pinfo->pp18_gpio),835							 "failed to get pp18 gpio\n");836	}837 838	pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH);839	if (IS_ERR(pinfo->pp33_gpio)) {840		return	dev_err_probe(dev, PTR_ERR(pinfo->pp33_gpio),841							 "failed to get pp33 gpio\n");842	}843 844	pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);845	if (IS_ERR(pinfo->enable_gpio)) {846		return	dev_err_probe(dev, PTR_ERR(pinfo->enable_gpio),847						 "failed to get enable gpio\n");848	}849 850	drm_panel_init(&pinfo->base, dev, &panel_funcs,851		       DRM_MODE_CONNECTOR_DSI);852 853	ret = drm_panel_of_backlight(&pinfo->base);854	if (ret)855		return ret;856 857	drm_panel_add(&pinfo->base);858 859	return 0;860}861 862static int panel_probe(struct mipi_dsi_device *dsi)863{864	struct panel_info *pinfo;865	const struct panel_desc *desc;866	int err;867 868	pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);869	if (!pinfo)870		return -ENOMEM;871 872	desc = of_device_get_match_data(&dsi->dev);873	dsi->mode_flags = desc->mode_flags;874	dsi->format = desc->format;875	dsi->lanes = desc->lanes;876	pinfo->desc = desc;877 878	pinfo->link = dsi;879	mipi_dsi_set_drvdata(dsi, pinfo);880 881	err = panel_add(pinfo);882	if (err < 0)883		return err;884 885	err = mipi_dsi_attach(dsi);886	if (err < 0)887		drm_panel_remove(&pinfo->base);888 889	return err;890}891 892static void panel_remove(struct mipi_dsi_device *dsi)893{894	struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);895	int err;896 897	err = mipi_dsi_detach(dsi);898	if (err < 0)899		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);900 901	drm_panel_remove(&pinfo->base);902}903 904static struct mipi_dsi_driver panel_driver = {905	.driver = {906		.name = "panel-boe-himax8279d",907		.of_match_table = panel_of_match,908	},909	.probe = panel_probe,910	.remove = panel_remove,911};912module_mipi_dsi_driver(panel_driver);913 914MODULE_AUTHOR("Jerry Han <jerry.han.hq@gmail.com>");915MODULE_DESCRIPTION("Boe Himax8279d driver");916MODULE_LICENSE("GPL v2");917