~ubuntu-branches/ubuntu/trusty/linux-armadaxp/trusty

« back to all changes in this revision

Viewing changes to drivers/staging/gma500/mdfld_pyr_cmd.c

  • Committer: Package Import Robot
  • Author(s): Michael Casadevall, Bryan Wu, Dann Frazier, Michael Casadeall
  • Date: 2012-03-10 15:00:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120310150054-flugb39zon8vvgwe
Tags: 3.2.0-1600.1
[ Bryan Wu ]
* UBUNTU: import debian/debian.env and debian.armadaxp

[ Dann Frazier ]
* ARM: Armada XP: remove trailing '/' in dirnames in mvRules.mk

[ Michael Casadeall ]
* tools: add some tools for Marvell Armada XP processor
* kernel: timer tick hacking from Marvell
* kernel: Sheeva Errata: add delay on Sheeva when powering down
* net: add Marvell NFP netfilter
* net: socket and skb modifications made by Marvell
* miscdevice: add minor IDs for some Marvell Armada drivers
* fs: introduce memory pool for splice()
* video: EDID detection updates from Marvell Armada XP patchset
* video: backlight: add Marvell Dove LCD backlight driver
* video: display: add THS8200 display driver
* video: framebuffer: add Marvell Dove and Armada XP processor onchip LCD controller driver
* usbtest: add Interrupt transfer testing by Marvell Armada XP code
* usb: ehci: add support for Marvell EHCI controler
* tty/serial: 8250: add support for Marvell Armada XP processor and DeviceTree work
* rtc: add support for Marvell Armada XP onchip RTC controller
* net: pppoe: add Marvell ethernet NFP hook in PPPoE networking driver
* mtd: nand: add support for Marvell Armada XP Nand Flash Controller
* mtd: maps: add Marvell Armada XP specific map driver
* mmc: add support for Marvell Armada XP MMC/SD host controller
* i2c: add support for Marvell Armada XP onchip i2c bus controller
* hwmon: add Kconfig option for Armada XP onchip thermal sensor driver
* dmaengine: add Net DMA support for splice and update Marvell XOR DMA engine driver
* ata: add support for Marvell Armada XP SATA controller and update some quirks
* ARM: add Marvell Armada XP machine to mach-types
* ARM: oprofile: add support for Marvell PJ4B core
* ARM: mm: more ARMv6 switches for Marvell Armada XP
* ARM: remove static declaration to allow compilation
* ARM: alignment access fault trick
* ARM: mm: skip some fault fixing when run on NONE SMP ARMv6 mode during early abort event
* ARM: mm: add Marvell Sheeva CPU Architecture for PJ4B
* ARM: introduce optimized copy operation for Marvell Armada XP
* ARM: SAUCE: hardware breakpoint trick for Marvell Armada XP
* ARM: big endian and little endian tricks for Marvell Armada XP
* ARM: SAUCE: Add Marvell Armada XP build rules to arch/arm/kernel/Makefile
* ARM: vfp: add special handling for Marvell Armada XP
* ARM: add support for Marvell U-Boot
* ARM: add mv_controller_num for ARM PCI drivers
* ARM: add support for local PMUs, general SMP tweaks and cache flushing
* ARM: add Marvell device identifies in glue-proc.h
* ARM: add IPC driver support for Marvell platforms
* ARM: add DMA mapping for Marvell platforms
* ARM: add Sheeva errata and PJ4B code for booting
* ARM: update Kconfig and Makefile to include Marvell Armada XP platforms
* ARM: Armada XP: import LSP from Marvell for Armada XP 3.2 kernel enablement

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c)  2010 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, sublicensen
 
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
 * Authors:
 
24
 * Thomas Eaton <thomas.g.eaton@intel.com>
 
25
 * Scott Rowe <scott.m.rowe@intel.com>
 
26
*/
 
27
 
 
28
#include "mdfld_dsi_dbi.h"
 
29
#include "mdfld_dsi_dpi.h"
 
30
#include "mdfld_dsi_output.h"
 
31
#include "mdfld_output.h"
 
32
#include "mdfld_dsi_dbi_dpu.h"
 
33
#include "mdfld_dsi_pkg_sender.h"
 
34
 
 
35
#include "displays/pyr_cmd.h"
 
36
 
 
37
static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
 
38
{
 
39
        struct drm_display_mode *mode;
 
40
 
 
41
        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 
42
        if (!mode) {
 
43
                dev_err(dev->dev, "Out of memory\n");
 
44
                return NULL;
 
45
        }
 
46
 
 
47
        dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
 
48
        dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
 
49
        dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
 
50
        dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
 
51
        dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
 
52
        dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
 
53
        dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
 
54
        dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
 
55
        dev_dbg(dev->dev, "clock is %d\n", mode->clock);
 
56
 
 
57
        mode->hdisplay = 480;
 
58
        mode->vdisplay = 864;
 
59
        mode->hsync_start = 487;
 
60
        mode->hsync_end = 490;
 
61
        mode->htotal = 499;
 
62
        mode->vsync_start = 874;
 
63
        mode->vsync_end = 878;
 
64
        mode->vtotal = 886;
 
65
        mode->clock = 25777;
 
66
 
 
67
        drm_mode_set_name(mode);
 
68
        drm_mode_set_crtcinfo(mode, 0);
 
69
 
 
70
        mode->type |= DRM_MODE_TYPE_PREFERRED;
 
71
 
 
72
        return mode;
 
73
}
 
74
 
 
75
static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
 
76
                                struct drm_display_mode *mode,
 
77
                                struct drm_display_mode *adjusted_mode)
 
78
{
 
79
        struct drm_device *dev = encoder->dev;
 
80
        struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
 
81
 
 
82
        if (fixed_mode) {
 
83
                adjusted_mode->hdisplay = fixed_mode->hdisplay;
 
84
                adjusted_mode->hsync_start = fixed_mode->hsync_start;
 
85
                adjusted_mode->hsync_end = fixed_mode->hsync_end;
 
86
                adjusted_mode->htotal = fixed_mode->htotal;
 
87
                adjusted_mode->vdisplay = fixed_mode->vdisplay;
 
88
                adjusted_mode->vsync_start = fixed_mode->vsync_start;
 
89
                adjusted_mode->vsync_end = fixed_mode->vsync_end;
 
90
                adjusted_mode->vtotal = fixed_mode->vtotal;
 
91
                adjusted_mode->clock = fixed_mode->clock;
 
92
                drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 
93
                kfree(fixed_mode);
 
94
        }
 
95
        return true;
 
96
}
 
97
 
 
98
static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
 
99
{
 
100
        int ret = 0;
 
101
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
 
102
        struct mdfld_dsi_dbi_output *dbi_output =
 
103
                                MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
 
104
        struct drm_device *dev = encoder->dev;
 
105
        struct drm_psb_private *dev_priv = dev->dev_private;
 
106
        u32 reg_offset = 0;
 
107
        int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
 
108
 
 
109
        dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
 
110
                        on ? "On" : "Off",
 
111
                        dbi_output->dbi_panel_on ? "True" : "False");
 
112
 
 
113
        if (pipe == 2) {
 
114
                if (on)
 
115
                        dev_priv->dual_mipi = true;
 
116
                else
 
117
                        dev_priv->dual_mipi = false;
 
118
 
 
119
                reg_offset = MIPIC_REG_OFFSET;
 
120
        } else {
 
121
                if (!on)
 
122
                        dev_priv->dual_mipi = false;
 
123
        }
 
124
 
 
125
        if (!gma_power_begin(dev, true)) {
 
126
                dev_err(dev->dev, "hw begin failed\n");
 
127
                return;
 
128
        }
 
129
 
 
130
 
 
131
        if (on) {
 
132
                if (dbi_output->dbi_panel_on)
 
133
                        goto out_err;
 
134
 
 
135
                ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
 
136
                if (ret) {
 
137
                        dev_err(dev->dev, "power on error\n");
 
138
                        goto out_err;
 
139
                }
 
140
 
 
141
                dbi_output->dbi_panel_on = true;
 
142
 
 
143
                if (pipe == 2) {
 
144
                        dev_priv->dbi_panel_on2 = true;
 
145
                } else {
 
146
                        dev_priv->dbi_panel_on = true;
 
147
                        mdfld_enable_te(dev, 0);
 
148
                }
 
149
        } else {
 
150
                if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
 
151
                        goto out_err;
 
152
 
 
153
                dbi_output->dbi_panel_on = false;
 
154
                dbi_output->first_boot = false;
 
155
 
 
156
                if (pipe == 2) {
 
157
                        dev_priv->dbi_panel_on2 = false;
 
158
                        mdfld_disable_te(dev, 2);
 
159
                } else {
 
160
                        dev_priv->dbi_panel_on = false;
 
161
                        mdfld_disable_te(dev, 0);
 
162
 
 
163
                        if (dev_priv->dbi_panel_on2)
 
164
                                mdfld_enable_te(dev, 2);
 
165
                }
 
166
 
 
167
                ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
 
168
                if (ret) {
 
169
                        dev_err(dev->dev, "power on error\n");
 
170
                        goto out_err;
 
171
                }
 
172
        }
 
173
 
 
174
out_err:
 
175
        gma_power_end(dev);
 
176
 
 
177
        if (ret)
 
178
                dev_err(dev->dev, "failed\n");
 
179
}
 
180
 
 
181
static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
 
182
                                                                int pipe)
 
183
{
 
184
        struct drm_device *dev = dsi_config->dev;
 
185
        u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
 
186
        int lane_count = dsi_config->lane_count;
 
187
        u32 val = 0;
 
188
 
 
189
        dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
 
190
 
 
191
        /* Un-ready device */
 
192
        REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
 
193
 
 
194
        /* Init dsi adapter before kicking off */
 
195
        REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
 
196
 
 
197
        /* TODO: figure out how to setup these registers */
 
198
        REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
 
199
        REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
 
200
                                                                0x000a0014);
 
201
        REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
 
202
        REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
 
203
 
 
204
        /* Enable all interrupts */
 
205
        REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
 
206
        /* Max value: 20 clock cycles of txclkesc */
 
207
        REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
 
208
        /* Min 21 txclkesc, max: ffffh */
 
209
        REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
 
210
        /* Min: 7d0 max: 4e20 */
 
211
        REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
 
212
 
 
213
        /* Set up func_prg */
 
214
        val |= lane_count;
 
215
        val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
 
216
        val |= DSI_DBI_COLOR_FORMAT_OPTION2;
 
217
        REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
 
218
 
 
219
        REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
 
220
        REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
 
221
 
 
222
        /* De-assert dbi_stall when half of DBI FIFO is empty */
 
223
        /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
 
224
 
 
225
        REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
 
226
        REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
 
227
        REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
 
228
        REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
 
229
}
 
230
 
 
231
static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
 
232
                                struct drm_display_mode *mode,
 
233
                                struct drm_display_mode *adjusted_mode)
 
234
{
 
235
        int ret = 0;
 
236
        struct drm_device *dev = encoder->dev;
 
237
        struct drm_psb_private *dev_priv = dev->dev_private;
 
238
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
 
239
        struct mdfld_dsi_dbi_output *dsi_output =
 
240
                                        MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
 
241
        struct mdfld_dsi_config *dsi_config =
 
242
                                mdfld_dsi_encoder_get_config(dsi_encoder);
 
243
        struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
 
244
        int pipe = dsi_connector->pipe;
 
245
        u8 param = 0;
 
246
 
 
247
        /* Regs */
 
248
        u32 mipi_reg = MIPI;
 
249
        u32 dspcntr_reg = DSPACNTR;
 
250
        u32 pipeconf_reg = PIPEACONF;
 
251
        u32 reg_offset = 0;
 
252
 
 
253
        /* Values */
 
254
        u32 dspcntr_val = dev_priv->dspcntr;
 
255
        u32 pipeconf_val = dev_priv->pipeconf;
 
256
        u32 h_active_area = mode->hdisplay;
 
257
        u32 v_active_area = mode->vdisplay;
 
258
        u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
 
259
                                                        TE_TRIGGER_GPIO_PIN);
 
260
 
 
261
        dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
 
262
 
 
263
        dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
 
264
        dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
 
265
 
 
266
        if (pipe == 2) {
 
267
                mipi_reg = MIPI_C;
 
268
                dspcntr_reg = DSPCCNTR;
 
269
                pipeconf_reg = PIPECCONF;
 
270
 
 
271
                reg_offset = MIPIC_REG_OFFSET;
 
272
 
 
273
                dspcntr_val = dev_priv->dspcntr2;
 
274
                pipeconf_val = dev_priv->pipeconf2;
 
275
        } else {
 
276
                mipi_val |= 0x2; /* Two lanes for port A and C respectively */
 
277
        }
 
278
 
 
279
        if (!gma_power_begin(dev, true)) {
 
280
                dev_err(dev->dev, "hw begin failed\n");
 
281
                return;
 
282
        }
 
283
 
 
284
        /* Set up pipe related registers */
 
285
        REG_WRITE(mipi_reg, mipi_val);
 
286
        REG_READ(mipi_reg);
 
287
 
 
288
        pyr_dsi_controller_dbi_init(dsi_config, pipe);
 
289
 
 
290
        msleep(20);
 
291
 
 
292
        REG_WRITE(dspcntr_reg, dspcntr_val);
 
293
        REG_READ(dspcntr_reg);
 
294
 
 
295
        /* 20ms delay before sending exit_sleep_mode */
 
296
        msleep(20);
 
297
 
 
298
        /* Send exit_sleep_mode DCS */
 
299
        ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
 
300
                                                0, CMD_DATA_SRC_SYSTEM_MEM);
 
301
        if (ret) {
 
302
                dev_err(dev->dev, "sent exit_sleep_mode faild\n");
 
303
                goto out_err;
 
304
        }
 
305
 
 
306
        /*send set_tear_on DCS*/
 
307
        ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
 
308
                                        &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
 
309
        if (ret) {
 
310
                dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
 
311
                goto out_err;
 
312
        }
 
313
 
 
314
        /* Do some init stuff */
 
315
        mdfld_dsi_brightness_init(dsi_config, pipe);
 
316
        mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
 
317
                                HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
 
318
 
 
319
        REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
 
320
        REG_READ(pipeconf_reg);
 
321
 
 
322
        /* TODO: this looks ugly, try to move it to CRTC mode setting */
 
323
        if (pipe == 2)
 
324
                dev_priv->pipeconf2 |= PIPEACONF_DSR;
 
325
        else
 
326
                dev_priv->pipeconf |= PIPEACONF_DSR;
 
327
 
 
328
        dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
 
329
 
 
330
        ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
 
331
                                h_active_area - 1, v_active_area - 1);
 
332
        if (ret) {
 
333
                dev_err(dev->dev, "update area failed\n");
 
334
                goto out_err;
 
335
        }
 
336
 
 
337
out_err:
 
338
        gma_power_end(dev);
 
339
 
 
340
        if (ret)
 
341
                dev_err(dev->dev, "mode set failed\n");
 
342
        else
 
343
                dev_dbg(dev->dev, "mode set done successfully\n");
 
344
}
 
345
 
 
346
static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
 
347
{
 
348
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
 
349
        struct mdfld_dsi_dbi_output *dbi_output =
 
350
                                        MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
 
351
 
 
352
        dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
 
353
        dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
 
354
 
 
355
        pyr_dsi_dbi_set_power(encoder, false);
 
356
}
 
357
 
 
358
static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
 
359
{
 
360
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
 
361
        struct mdfld_dsi_dbi_output *dbi_output =
 
362
                                        MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
 
363
        struct drm_device *dev = dbi_output->dev;
 
364
        struct drm_psb_private *dev_priv = dev->dev_private;
 
365
        struct psb_drm_dpu_rect rect;
 
366
 
 
367
        pyr_dsi_dbi_set_power(encoder, true);
 
368
 
 
369
        dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
 
370
 
 
371
        rect.x = rect.y = 0;
 
372
        rect.width = 864;
 
373
        rect.height = 480;
 
374
 
 
375
        if (dbi_output->channel_num == 1) {
 
376
                dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
 
377
                /* If DPU enabled report a fullscreen damage */
 
378
                mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
 
379
        } else {
 
380
                dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
 
381
                mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
 
382
        }
 
383
        dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
 
384
}
 
385
 
 
386
static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
 
387
{
 
388
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
 
389
        struct mdfld_dsi_dbi_output *dbi_output =
 
390
                                        MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
 
391
        struct drm_device *dev = dbi_output->dev;
 
392
 
 
393
        dev_dbg(dev->dev, "%s\n",  (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
 
394
 
 
395
        if (mode == DRM_MODE_DPMS_ON)
 
396
                pyr_dsi_dbi_set_power(encoder, true);
 
397
        else
 
398
                pyr_dsi_dbi_set_power(encoder, false);
 
399
}
 
400
 
 
401
/*
 
402
 * Update the DBI MIPI Panel Frame Buffer.
 
403
 */
 
404
static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
 
405
                                                                int pipe)
 
406
{
 
407
        struct mdfld_dsi_pkg_sender *sender =
 
408
                mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
 
409
        struct drm_device *dev = dbi_output->dev;
 
410
        struct drm_crtc *crtc = dbi_output->base.base.crtc;
 
411
        struct psb_intel_crtc *psb_crtc = (crtc) ?
 
412
                                to_psb_intel_crtc(crtc) : NULL;
 
413
 
 
414
        u32 dpll_reg = MRST_DPLL_A;
 
415
        u32 dspcntr_reg = DSPACNTR;
 
416
        u32 pipeconf_reg = PIPEACONF;
 
417
        u32 dsplinoff_reg = DSPALINOFF;
 
418
        u32 dspsurf_reg = DSPASURF;
 
419
        u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
 
420
        u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
 
421
        u32 reg_offset = 0;
 
422
 
 
423
        u32 intr_status;
 
424
        u32 fifo_stat_reg_val;
 
425
        u32 dpll_reg_val;
 
426
        u32 dspcntr_reg_val;
 
427
        u32 pipeconf_reg_val;
 
428
 
 
429
        /* If mode setting on-going, back off */
 
430
        if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
 
431
                (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
 
432
                !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
 
433
                return;
 
434
 
 
435
        /*
 
436
         * Look for errors here.  In particular we're checking for whatever
 
437
         * error status might have appeared during the last frame transmit
 
438
         * (memory write).
 
439
         *
 
440
         * Normally, the bits we're testing here would be set infrequently,
 
441
         * if at all.  However, one panel (at least) returns at least one
 
442
         * error bit on most frames.  So we've disabled the kernel message
 
443
         * for now.
 
444
         *
 
445
         * Still clear whatever error bits are set, except don't clear the
 
446
         * ones that would make the Penwell DSI controller reset if we
 
447
         * cleared them.
 
448
         */
 
449
        intr_status = REG_READ(INTR_STAT_REG);
 
450
        if ((intr_status & 0x26FFFFFF) != 0) {
 
451
                /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
 
452
                intr_status &= 0x26F3FFFF;
 
453
                REG_WRITE(INTR_STAT_REG, intr_status);
 
454
        }
 
455
 
 
456
        if (pipe == 2) {
 
457
                dspcntr_reg = DSPCCNTR;
 
458
                pipeconf_reg = PIPECCONF;
 
459
                dsplinoff_reg = DSPCLINOFF;
 
460
                dspsurf_reg = DSPCSURF;
 
461
 
 
462
                hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
 
463
                gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
 
464
 
 
465
                reg_offset = MIPIC_REG_OFFSET;
 
466
        }
 
467
 
 
468
        if (!gma_power_begin(dev, true)) {
 
469
                dev_err(dev->dev, "hw begin failed\n");
 
470
                return;
 
471
        }
 
472
 
 
473
        fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
 
474
        dpll_reg_val = REG_READ(dpll_reg);
 
475
        dspcntr_reg_val = REG_READ(dspcntr_reg);
 
476
        pipeconf_reg_val = REG_READ(pipeconf_reg);
 
477
 
 
478
        if (!(fifo_stat_reg_val & (1 << 27)) ||
 
479
                (dpll_reg_val & DPLL_VCO_ENABLE) ||
 
480
                !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
 
481
                !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
 
482
                goto update_fb_out0;
 
483
        }
 
484
 
 
485
        /* Refresh plane changes */
 
486
        REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
 
487
        REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
 
488
        REG_READ(dspsurf_reg);
 
489
 
 
490
        mdfld_dsi_send_dcs(sender,
 
491
                           write_mem_start,
 
492
                           NULL,
 
493
                           0,
 
494
                           CMD_DATA_SRC_PIPE,
 
495
                           MDFLD_DSI_SEND_PACKAGE);
 
496
 
 
497
        /*
 
498
         * The idea here is to transmit a Generic Read command after the
 
499
         * Write Memory Start/Continue commands finish.  This asks for
 
500
         * the panel to return an "ACK No Errors," or (if it has errors
 
501
         * to report) an Error Report.  This allows us to monitor the
 
502
         * panel's perception of the health of the DSI.
 
503
         */
 
504
        mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
 
505
                                HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
 
506
        REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
 
507
 
 
508
        dbi_output->dsr_fb_update_done = true;
 
509
update_fb_out0:
 
510
        gma_power_end(dev);
 
511
}
 
512
 
 
513
/*
 
514
 * TODO: will be removed later, should work out display interfaces for power
 
515
 */
 
516
void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
 
517
{
 
518
        if (!dsi_config || (pipe != 0 && pipe != 2)) {
 
519
                WARN_ON(1);
 
520
                return;
 
521
        }
 
522
        pyr_dsi_controller_dbi_init(dsi_config, pipe);
 
523
}
 
524
 
 
525
static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
 
526
                                                        struct panel_info *pi)
 
527
{
 
528
        if (!dev || !pi)
 
529
                return -EINVAL;
 
530
 
 
531
        pi->width_mm = PYR_PANEL_WIDTH;
 
532
        pi->height_mm = PYR_PANEL_HEIGHT;
 
533
 
 
534
        return 0;
 
535
}
 
536
 
 
537
/* PYR DBI encoder helper funcs */
 
538
static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
 
539
        .dpms = pyr_dsi_dbi_dpms,
 
540
        .mode_fixup = pyr_dsi_dbi_mode_fixup,
 
541
        .prepare = pyr_dsi_dbi_prepare,
 
542
        .mode_set = pyr_dsi_dbi_mode_set,
 
543
        .commit = pyr_dsi_dbi_commit,
 
544
};
 
545
 
 
546
/* PYR DBI encoder funcs */
 
547
static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
 
548
        .destroy = drm_encoder_cleanup,
 
549
};
 
550
 
 
551
void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
 
552
{
 
553
        p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
 
554
        p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
 
555
        p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
 
556
        p_funcs->update_fb = pyr_dsi_dbi_update_fb;
 
557
        p_funcs->get_panel_info = pyr_cmd_get_panel_info;
 
558
}