Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright © 2011 Intel Corporation
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 21 * DEALINGS IN THE SOFTWARE.
 22 *
 23 */
 24
 25#include <linux/delay.h>
 26#include <linux/kernel.h>
 27#include <linux/module.h>
 28#include <linux/gpio/consumer.h>
 29
 30#include <asm/intel_scu_ipc.h>
 31
 32#include "mdfld_dsi_dpi.h"
 33#include "mdfld_dsi_pkg_sender.h"
 34#include "mdfld_output.h"
 35#include "tc35876x-dsi-lvds.h"
 36
 37static struct i2c_client *tc35876x_client;
 38static struct i2c_client *cmi_lcd_i2c_client;
 39/* Panel GPIOs */
 40static struct gpio_desc *bridge_reset;
 41static struct gpio_desc *bridge_bl_enable;
 42static struct gpio_desc *backlight_voltage;
 43
 44
 45#define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
 46#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
 47
 48/* DSI D-PHY Layer Registers */
 49#define D0W_DPHYCONTTX		0x0004
 50#define CLW_DPHYCONTRX		0x0020
 51#define D0W_DPHYCONTRX		0x0024
 52#define D1W_DPHYCONTRX		0x0028
 53#define D2W_DPHYCONTRX		0x002C
 54#define D3W_DPHYCONTRX		0x0030
 55#define COM_DPHYCONTRX		0x0038
 56#define CLW_CNTRL		0x0040
 57#define D0W_CNTRL		0x0044
 58#define D1W_CNTRL		0x0048
 59#define D2W_CNTRL		0x004C
 60#define D3W_CNTRL		0x0050
 61#define DFTMODE_CNTRL		0x0054
 62
 63/* DSI PPI Layer Registers */
 64#define PPI_STARTPPI		0x0104
 65#define PPI_BUSYPPI		0x0108
 66#define PPI_LINEINITCNT		0x0110
 67#define PPI_LPTXTIMECNT		0x0114
 68#define PPI_LANEENABLE		0x0134
 69#define PPI_TX_RX_TA		0x013C
 70#define PPI_CLS_ATMR		0x0140
 71#define PPI_D0S_ATMR		0x0144
 72#define PPI_D1S_ATMR		0x0148
 73#define PPI_D2S_ATMR		0x014C
 74#define PPI_D3S_ATMR		0x0150
 75#define PPI_D0S_CLRSIPOCOUNT	0x0164
 76#define PPI_D1S_CLRSIPOCOUNT	0x0168
 77#define PPI_D2S_CLRSIPOCOUNT	0x016C
 78#define PPI_D3S_CLRSIPOCOUNT	0x0170
 79#define CLS_PRE			0x0180
 80#define D0S_PRE			0x0184
 81#define D1S_PRE			0x0188
 82#define D2S_PRE			0x018C
 83#define D3S_PRE			0x0190
 84#define CLS_PREP		0x01A0
 85#define D0S_PREP		0x01A4
 86#define D1S_PREP		0x01A8
 87#define D2S_PREP		0x01AC
 88#define D3S_PREP		0x01B0
 89#define CLS_ZERO		0x01C0
 90#define D0S_ZERO		0x01C4
 91#define D1S_ZERO		0x01C8
 92#define D2S_ZERO		0x01CC
 93#define D3S_ZERO		0x01D0
 94#define PPI_CLRFLG		0x01E0
 95#define PPI_CLRSIPO		0x01E4
 96#define HSTIMEOUT		0x01F0
 97#define HSTIMEOUTENABLE		0x01F4
 98
 99/* DSI Protocol Layer Registers */
100#define DSI_STARTDSI		0x0204
101#define DSI_BUSYDSI		0x0208
102#define DSI_LANEENABLE		0x0210
103#define DSI_LANESTATUS0		0x0214
104#define DSI_LANESTATUS1		0x0218
105#define DSI_INTSTATUS		0x0220
106#define DSI_INTMASK		0x0224
107#define DSI_INTCLR		0x0228
108#define DSI_LPTXTO		0x0230
109
110/* DSI General Registers */
111#define DSIERRCNT		0x0300
112
113/* DSI Application Layer Registers */
114#define APLCTRL			0x0400
115#define RDPKTLN			0x0404
116
117/* Video Path Registers */
118#define VPCTRL			0x0450
119#define HTIM1			0x0454
120#define HTIM2			0x0458
121#define VTIM1			0x045C
122#define VTIM2			0x0460
123#define VFUEN			0x0464
124
125/* LVDS Registers */
126#define LVMX0003		0x0480
127#define LVMX0407		0x0484
128#define LVMX0811		0x0488
129#define LVMX1215		0x048C
130#define LVMX1619		0x0490
131#define LVMX2023		0x0494
132#define LVMX2427		0x0498
133#define LVCFG			0x049C
134#define LVPHY0			0x04A0
135#define LVPHY1			0x04A4
136
137/* System Registers */
138#define SYSSTAT			0x0500
139#define SYSRST			0x0504
140
141/* GPIO Registers */
142/*#define GPIOC			0x0520*/
143#define GPIOO			0x0524
144#define GPIOI			0x0528
145
146/* I2C Registers */
147#define I2CTIMCTRL		0x0540
148#define I2CMADDR		0x0544
149#define WDATAQ			0x0548
150#define RDATAQ			0x054C
151
152/* Chip/Rev Registers */
153#define IDREG			0x0580
154
155/* Debug Registers */
156#define DEBUG00			0x05A0
157#define DEBUG01			0x05A4
158
159/* Panel CABC registers */
160#define PANEL_PWM_CONTROL	0x90
161#define PANEL_FREQ_DIVIDER_HI	0x91
162#define PANEL_FREQ_DIVIDER_LO	0x92
163#define PANEL_DUTY_CONTROL	0x93
164#define PANEL_MODIFY_RGB	0x94
165#define PANEL_FRAMERATE_CONTROL	0x96
166#define PANEL_PWM_MIN		0x97
167#define PANEL_PWM_REF		0x98
168#define PANEL_PWM_MAX		0x99
169#define PANEL_ALLOW_DISTORT	0x9A
170#define PANEL_BYPASS_PWMI	0x9B
171
172/* Panel color management registers */
173#define PANEL_CM_ENABLE		0x700
174#define PANEL_CM_HUE		0x701
175#define PANEL_CM_SATURATION	0x702
176#define PANEL_CM_INTENSITY	0x703
177#define PANEL_CM_BRIGHTNESS	0x704
178#define PANEL_CM_CE_ENABLE	0x705
179#define PANEL_CM_PEAK_EN	0x710
180#define PANEL_CM_GAIN		0x711
181#define PANEL_CM_HUETABLE_START	0x730
182#define PANEL_CM_HUETABLE_END	0x747 /* inclusive */
183
184/* Input muxing for registers LVMX0003...LVMX2427 */
185enum {
186	INPUT_R0,	/* 0 */
187	INPUT_R1,
188	INPUT_R2,
189	INPUT_R3,
190	INPUT_R4,
191	INPUT_R5,
192	INPUT_R6,
193	INPUT_R7,
194	INPUT_G0,	/* 8 */
195	INPUT_G1,
196	INPUT_G2,
197	INPUT_G3,
198	INPUT_G4,
199	INPUT_G5,
200	INPUT_G6,
201	INPUT_G7,
202	INPUT_B0,	/* 16 */
203	INPUT_B1,
204	INPUT_B2,
205	INPUT_B3,
206	INPUT_B4,
207	INPUT_B5,
208	INPUT_B6,
209	INPUT_B7,
210	INPUT_HSYNC,	/* 24 */
211	INPUT_VSYNC,
212	INPUT_DE,
213	LOGIC_0,
214	/* 28...31 undefined */
215};
216
217#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00)		\
218	(FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) |	\
219	FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
220
221/**
222 * tc35876x_regw - Write DSI-LVDS bridge register using I2C
223 * @client: struct i2c_client to use
224 * @reg: register address
225 * @value: value to write
226 *
227 * Returns 0 on success, or a negative error value.
228 */
229static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
230{
231	int r;
232	u8 tx_data[] = {
233		/* NOTE: Register address big-endian, data little-endian. */
234		(reg >> 8) & 0xff,
235		reg & 0xff,
236		value & 0xff,
237		(value >> 8) & 0xff,
238		(value >> 16) & 0xff,
239		(value >> 24) & 0xff,
240	};
241	struct i2c_msg msgs[] = {
242		{
243			.addr = client->addr,
244			.flags = 0,
245			.buf = tx_data,
246			.len = ARRAY_SIZE(tx_data),
247		},
248	};
249
250	r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
251	if (r < 0) {
252		dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
253			__func__, reg, value, r);
254		return r;
255	}
256
257	if (r < ARRAY_SIZE(msgs)) {
258		dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
259			__func__, reg, value, r);
260		return -EAGAIN;
261	}
262
263	dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
264			__func__, reg, value);
265
266	return 0;
267}
268
269/**
270 * tc35876x_regr - Read DSI-LVDS bridge register using I2C
271 * @client: struct i2c_client to use
272 * @reg: register address
273 * @value: pointer for storing the value
274 *
275 * Returns 0 on success, or a negative error value.
276 */
277static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
278{
279	int r;
280	u8 tx_data[] = {
281		(reg >> 8) & 0xff,
282		reg & 0xff,
283	};
284	u8 rx_data[4];
285	struct i2c_msg msgs[] = {
286		{
287			.addr = client->addr,
288			.flags = 0,
289			.buf = tx_data,
290			.len = ARRAY_SIZE(tx_data),
291		},
292		{
293			.addr = client->addr,
294			.flags = I2C_M_RD,
295			.buf = rx_data,
296			.len = ARRAY_SIZE(rx_data),
297		 },
298	};
299
300	r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
301	if (r < 0) {
302		dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
303			reg, r);
304		return r;
305	}
306
307	if (r < ARRAY_SIZE(msgs)) {
308		dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
309			reg, r);
310		return -EAGAIN;
311	}
312
313	*value = rx_data[0] << 24 | rx_data[1] << 16 |
314		rx_data[2] << 8 | rx_data[3];
315
316	dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
317		reg, *value);
318
319	return 0;
320}
321
322void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
323{
324	if (WARN(!tc35876x_client, "%s called before probe", __func__))
325		return;
326
327	dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
328
329	if (!bridge_reset)
330		return;
331
332	if (state) {
333		gpiod_set_value_cansleep(bridge_reset, 0);
334		mdelay(10);
335	} else {
336		/* Pull MIPI Bridge reset pin to Low */
337		gpiod_set_value_cansleep(bridge_reset, 0);
338		mdelay(20);
339		/* Pull MIPI Bridge reset pin to High */
340		gpiod_set_value_cansleep(bridge_reset, 1);
341		mdelay(40);
342	}
343}
344
345void tc35876x_configure_lvds_bridge(struct drm_device *dev)
346{
347	struct i2c_client *i2c = tc35876x_client;
348	u32 ppi_lptxtimecnt;
349	u32 txtagocnt;
350	u32 txtasurecnt;
351	u32 id;
352
353	if (WARN(!tc35876x_client, "%s called before probe", __func__))
354		return;
355
356	dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
357
358	if (!tc35876x_regr(i2c, IDREG, &id))
359		dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
360	else
361		dev_err(&tc35876x_client->dev, "Cannot read ID\n");
362
363	ppi_lptxtimecnt = 4;
364	txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
365	txtasurecnt = 3 * ppi_lptxtimecnt / 2;
366	tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
367		FLD_VAL(txtasurecnt, 10, 0));
368	tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
369
370	tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
371	tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
372	tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
373	tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
374
375	/* Enabling MIPI & PPI lanes, Enable 4 lanes */
376	tc35876x_regw(i2c, PPI_LANEENABLE,
377		BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
378	tc35876x_regw(i2c, DSI_LANEENABLE,
379		BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
380	tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
381	tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
382
383	/* Setting LVDS output frequency */
384	tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
385		FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
386
387	/* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
388	tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
389
390	/* Horizontal back porch and horizontal pulse width. 0x00280028 */
391	tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
392
393	/* Horizontal front porch and horizontal active video size. 0x00500500*/
394	tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
395
396	/* Vertical back porch and vertical sync pulse width. 0x000e000a */
397	tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
398
399	/* Vertical front porch and vertical display size. 0x000e0320 */
400	tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
401
402	/* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
403	tc35876x_regw(i2c, VFUEN, BIT(0));
404
405	/* Soft reset LCD controller. */
406	tc35876x_regw(i2c, SYSRST, BIT(2));
407
408	/* LVDS-TX input muxing */
409	tc35876x_regw(i2c, LVMX0003,
410		INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
411	tc35876x_regw(i2c, LVMX0407,
412		INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
413	tc35876x_regw(i2c, LVMX0811,
414		INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
415	tc35876x_regw(i2c, LVMX1215,
416		INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
417	tc35876x_regw(i2c, LVMX1619,
418		INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
419	tc35876x_regw(i2c, LVMX2023,
420		INPUT_MUX(LOGIC_0,  INPUT_B7, INPUT_B6, INPUT_B5));
421	tc35876x_regw(i2c, LVMX2427,
422		INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
423
424	/* Enable LVDS transmitter. */
425	tc35876x_regw(i2c, LVCFG, BIT(0));
426
427	/* Clear notifications. Don't write reserved bits. Was write 0xffffffff
428	 * to 0x0288, must be in error?! */
429	tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
430}
431
432#define GPIOPWMCTRL	0x38F
433#define PWM0CLKDIV0	0x62 /* low byte */
434#define PWM0CLKDIV1	0x61 /* high byte */
435
436#define SYSTEMCLK	19200000UL /* 19.2 MHz */
437#define PWM_FREQUENCY	9600 /* Hz */
438
439/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
440static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
441{
442	return (baseclk - f) / f;
443}
444
445static void tc35876x_brightness_init(struct drm_device *dev)
446{
447	int ret;
448	u8 pwmctrl;
449	u16 clkdiv;
450
451	/* Make sure the PWM reference is the 19.2 MHz system clock. Read first
452	 * instead of setting directly to catch potential conflicts between PWM
453	 * users. */
454	ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
455	if (ret || pwmctrl != 0x01) {
456		if (ret)
457			dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
458		else
459			dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
460
461		ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
462		if (ret)
463			dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
464	}
465
466	clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
467
468	ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
469	if (!ret)
470		ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
471
472	if (ret)
473		dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
474	else
475		dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
476			clkdiv, PWM_FREQUENCY);
477}
478
479#define PWM0DUTYCYCLE			0x67
480
481void tc35876x_brightness_control(struct drm_device *dev, int level)
482{
483	int ret;
484	u8 duty_val;
485	u8 panel_duty_val;
486
487	level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
488
489	/* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
490	duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
491
492	/* I won't pretend to understand this formula. The panel spec is quite
493	 * bad engrish.
494	 */
495	panel_duty_val = (2 * level - 100) * 0xA9 /
496			 MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
497
498	ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
499	if (ret)
500		dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
501			__func__);
502
503	if (cmi_lcd_i2c_client) {
504		ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
505						PANEL_PWM_MAX, panel_duty_val);
506		if (ret < 0)
507			dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
508				__func__);
509	}
510}
511
512void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
513{
514	if (WARN(!tc35876x_client, "%s called before probe", __func__))
515		return;
516
517	dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
518
519	if (bridge_bl_enable)
520		gpiod_set_value_cansleep(bridge_bl_enable, 0);
521
522	if (backlight_voltage)
523		gpiod_set_value_cansleep(backlight_voltage, 0);
524}
525
526void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
527{
528	struct drm_psb_private *dev_priv = dev->dev_private;
529
530	if (WARN(!tc35876x_client, "%s called before probe", __func__))
531		return;
532
533	dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
534
535	if (backlight_voltage) {
536		gpiod_set_value_cansleep(backlight_voltage, 1);
537		msleep(260);
538	}
539
540	if (cmi_lcd_i2c_client) {
541		int ret;
542		dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
543		/* Bit 4 is average_saving. Setting it to 1, the brightness is
544		 * referenced to the average of the frame content. 0 means
545		 * reference to the maximum of frame contents. Bits 3:0 are
546		 * allow_distort. When set to a nonzero value, all color values
547		 * between 255-allow_distort*2 and 255 are mapped to the
548		 * 255-allow_distort*2 value.
549		 */
550		ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
551						PANEL_ALLOW_DISTORT, 0x10);
552		if (ret < 0)
553			dev_err(&cmi_lcd_i2c_client->dev,
554				"i2c write failed (%d)\n", ret);
555		ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
556						PANEL_BYPASS_PWMI, 0);
557		if (ret < 0)
558			dev_err(&cmi_lcd_i2c_client->dev,
559				"i2c write failed (%d)\n", ret);
560		/* Set minimum brightness value - this is tunable */
561		ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
562						PANEL_PWM_MIN, 0x35);
563		if (ret < 0)
564			dev_err(&cmi_lcd_i2c_client->dev,
565				"i2c write failed (%d)\n", ret);
566	}
567
568	if (bridge_bl_enable)
569		gpiod_set_value_cansleep(bridge_bl_enable, 1);
570
571	tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
572}
573
574static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
575{
576	struct drm_display_mode *mode;
577
578	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
579
580	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
581	if (!mode)
582		return NULL;
583
584	/* FIXME: do this properly. */
585	mode->hdisplay = 1280;
586	mode->vdisplay = 800;
587	mode->hsync_start = 1360;
588	mode->hsync_end = 1400;
589	mode->htotal = 1440;
590	mode->vsync_start = 814;
591	mode->vsync_end = 824;
592	mode->vtotal = 838;
593	mode->clock = 33324 << 1;
594
595	dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
596	dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
597	dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
598	dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
599	dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
600	dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
601	dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
602	dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
603	dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
604
605	drm_mode_set_name(mode);
606	drm_mode_set_crtcinfo(mode, 0);
607
608	mode->type |= DRM_MODE_TYPE_PREFERRED;
609
610	return mode;
611}
612
613/* DV1 Active area 216.96 x 135.6 mm */
614#define DV1_PANEL_WIDTH 217
615#define DV1_PANEL_HEIGHT 136
616
617static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
618				struct panel_info *pi)
619{
620	if (!dev || !pi)
621		return -EINVAL;
622
623	pi->width_mm = DV1_PANEL_WIDTH;
624	pi->height_mm = DV1_PANEL_HEIGHT;
625
626	return 0;
627}
628
629static int tc35876x_bridge_probe(struct i2c_client *client,
630				const struct i2c_device_id *id)
631{
632	dev_info(&client->dev, "%s\n", __func__);
633
634	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
635		dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
636			__func__);
637		return -ENODEV;
638	}
639
640	bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW);
641	if (IS_ERR(bridge_reset))
642		return PTR_ERR(bridge_reset);
643	if (bridge_reset)
644		gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
645
646	bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW);
647	if (IS_ERR(bridge_bl_enable))
648		return PTR_ERR(bridge_bl_enable);
649	if (bridge_bl_enable)
650		gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
651
652	backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW);
653	if (IS_ERR(backlight_voltage))
654		return PTR_ERR(backlight_voltage);
655	if (backlight_voltage)
656		gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
657
658	tc35876x_client = client;
659
660	return 0;
661}
662
663static int tc35876x_bridge_remove(struct i2c_client *client)
664{
665	dev_dbg(&client->dev, "%s\n", __func__);
666
667	tc35876x_client = NULL;
668
669	return 0;
670}
671
672static const struct i2c_device_id tc35876x_bridge_id[] = {
673	{ "i2c_disp_brig", 0 },
674	{ }
675};
676MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
677
678static struct i2c_driver tc35876x_bridge_i2c_driver = {
679	.driver = {
680		.name = "i2c_disp_brig",
681	},
682	.id_table = tc35876x_bridge_id,
683	.probe = tc35876x_bridge_probe,
684	.remove = tc35876x_bridge_remove,
685};
686
687/* LCD panel I2C */
688static int cmi_lcd_i2c_probe(struct i2c_client *client,
689			     const struct i2c_device_id *id)
690{
691	dev_info(&client->dev, "%s\n", __func__);
692
693	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
694		dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
695			__func__);
696		return -ENODEV;
697	}
698
699	cmi_lcd_i2c_client = client;
700
701	return 0;
702}
703
704static int cmi_lcd_i2c_remove(struct i2c_client *client)
705{
706	dev_dbg(&client->dev, "%s\n", __func__);
707
708	cmi_lcd_i2c_client = NULL;
709
710	return 0;
711}
712
713static const struct i2c_device_id cmi_lcd_i2c_id[] = {
714	{ "cmi-lcd", 0 },
715	{ }
716};
717MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
718
719static struct i2c_driver cmi_lcd_i2c_driver = {
720	.driver = {
721		.name = "cmi-lcd",
722	},
723	.id_table = cmi_lcd_i2c_id,
724	.probe = cmi_lcd_i2c_probe,
725	.remove = cmi_lcd_i2c_remove,
726};
727
728/* HACK to create I2C device while it's not created by platform code */
729#define CMI_LCD_I2C_ADAPTER	2
730#define CMI_LCD_I2C_ADDR	0x60
731
732static int cmi_lcd_hack_create_device(void)
733{
734	struct i2c_adapter *adapter;
735	struct i2c_client *client;
736	struct i2c_board_info info = {
737		.type = "cmi-lcd",
738		.addr = CMI_LCD_I2C_ADDR,
739	};
740
741	pr_debug("%s\n", __func__);
742
743	adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
744	if (!adapter) {
745		pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
746			CMI_LCD_I2C_ADAPTER);
747		return -EINVAL;
748	}
749
750	client = i2c_new_client_device(adapter, &info);
751	if (IS_ERR(client)) {
752		pr_err("%s: creating I2C device failed\n", __func__);
753		i2c_put_adapter(adapter);
754		return PTR_ERR(client);
755	}
756
757	return 0;
758}
759
760static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
761	.dpms = mdfld_dsi_dpi_dpms,
762	.mode_fixup = mdfld_dsi_dpi_mode_fixup,
763	.prepare = mdfld_dsi_dpi_prepare,
764	.mode_set = mdfld_dsi_dpi_mode_set,
765	.commit = mdfld_dsi_dpi_commit,
766};
767
768const struct panel_funcs mdfld_tc35876x_funcs = {
769	.encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
770	.get_config_mode = tc35876x_get_config_mode,
771	.get_panel_info = tc35876x_get_panel_info,
772};
773
774void tc35876x_init(struct drm_device *dev)
775{
776	int r;
777
778	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
779
780	cmi_lcd_hack_create_device();
781
782	r = i2c_add_driver(&cmi_lcd_i2c_driver);
783	if (r < 0)
784		dev_err(&dev->pdev->dev,
785			"%s: i2c_add_driver() for %s failed (%d)\n",
786			__func__, cmi_lcd_i2c_driver.driver.name, r);
787
788	r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
789	if (r < 0)
790		dev_err(&dev->pdev->dev,
791			"%s: i2c_add_driver() for %s failed (%d)\n",
792			__func__, tc35876x_bridge_i2c_driver.driver.name, r);
793
794	tc35876x_brightness_init(dev);
795}
796
797void tc35876x_exit(void)
798{
799	pr_debug("%s\n", __func__);
800
801	i2c_del_driver(&tc35876x_bridge_i2c_driver);
802
803	if (cmi_lcd_i2c_client)
804		i2c_del_driver(&cmi_lcd_i2c_driver);
805}