~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/video/omap2/dss/dispc.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include <linux/delay.h>
33
33
#include <linux/workqueue.h>
34
34
#include <linux/hardirq.h>
 
35
#include <linux/interrupt.h>
35
36
 
36
37
#include <plat/sram.h>
37
38
#include <plat/clock.h>
42
43
#include "dss_features.h"
43
44
 
44
45
/* DISPC */
45
 
#define DISPC_BASE                      0x48050400
46
 
 
47
46
#define DISPC_SZ_REGS                   SZ_4K
48
47
 
49
48
struct dispc_reg { u16 idx; };
74
73
#define DISPC_TIMING_H(ch)              DISPC_REG(ch != 2 ? 0x0064 : 0x0400)
75
74
#define DISPC_TIMING_V(ch)              DISPC_REG(ch != 2 ? 0x0068 : 0x0404)
76
75
#define DISPC_POL_FREQ(ch)              DISPC_REG(ch != 2 ? 0x006C : 0x0408)
77
 
#define DISPC_DIVISOR(ch)               DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
 
76
#define DISPC_DIVISORo(ch)              DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
78
77
#define DISPC_GLOBAL_ALPHA              DISPC_REG(0x0074)
79
78
#define DISPC_SIZE_DIG                  DISPC_REG(0x0078)
80
79
#define DISPC_SIZE_LCD(ch)              DISPC_REG(ch != 2 ? 0x007C : 0x03CC)
129
128
 
130
129
#define DISPC_VID_PRELOAD(n)            DISPC_REG(0x230 + (n)*0x04)
131
130
 
 
131
#define DISPC_DIVISOR                   DISPC_REG(0x0804)
132
132
 
133
133
#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
134
134
                                         DISPC_IRQ_OCP_ERR | \
178
178
};
179
179
 
180
180
static struct {
 
181
        struct platform_device *pdev;
181
182
        void __iomem    *base;
 
183
        int irq;
182
184
 
183
185
        u32     fifo_size[3];
184
186
 
230
232
        SR(TIMING_H(0));
231
233
        SR(TIMING_V(0));
232
234
        SR(POL_FREQ(0));
233
 
        SR(DIVISOR(0));
 
235
        SR(DIVISORo(0));
234
236
        SR(GLOBAL_ALPHA);
235
237
        SR(SIZE_DIG);
236
238
        SR(SIZE_LCD(0));
242
244
                SR(TIMING_H(2));
243
245
                SR(TIMING_V(2));
244
246
                SR(POL_FREQ(2));
245
 
                SR(DIVISOR(2));
 
247
                SR(DIVISORo(2));
246
248
                SR(CONFIG2);
247
249
        }
248
250
 
373
375
        SR(VID_FIR_COEF_V(1, 7));
374
376
 
375
377
        SR(VID_PRELOAD(1));
 
378
 
 
379
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
 
380
                SR(DIVISOR);
376
381
}
377
382
 
378
383
void dispc_restore_context(void)
389
394
        RR(TIMING_H(0));
390
395
        RR(TIMING_V(0));
391
396
        RR(POL_FREQ(0));
392
 
        RR(DIVISOR(0));
 
397
        RR(DIVISORo(0));
393
398
        RR(GLOBAL_ALPHA);
394
399
        RR(SIZE_DIG);
395
400
        RR(SIZE_LCD(0));
400
405
                RR(TIMING_H(2));
401
406
                RR(TIMING_V(2));
402
407
                RR(POL_FREQ(2));
403
 
                RR(DIVISOR(2));
 
408
                RR(DIVISORo(2));
404
409
                RR(CONFIG2);
405
410
        }
406
411
 
532
537
 
533
538
        RR(VID_PRELOAD(1));
534
539
 
 
540
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
 
541
                RR(DIVISOR);
 
542
 
535
543
        /* enable last, because LCD & DIGIT enable are here */
536
544
        RR(CONTROL);
537
545
        if (dss_has_feature(FEAT_MGR_LCD2))
552
560
static inline void enable_clocks(bool enable)
553
561
{
554
562
        if (enable)
555
 
                dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
563
                dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
556
564
        else
557
 
                dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
565
                dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
558
566
}
559
567
 
560
568
bool dispc_go_busy(enum omap_channel channel)
1000
1008
        enable_clocks(0);
1001
1009
}
1002
1010
 
 
1011
void dispc_enable_gamma_table(bool enable)
 
1012
{
 
1013
        /*
 
1014
         * This is partially implemented to support only disabling of
 
1015
         * the gamma table.
 
1016
         */
 
1017
        if (enable) {
 
1018
                DSSWARN("Gamma table enabling for TV not yet supported");
 
1019
                return;
 
1020
        }
 
1021
 
 
1022
        REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
 
1023
}
 
1024
 
1003
1025
static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1004
1026
{
1005
1027
        u32 val;
1129
1151
        u32 val;
1130
1152
        const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
1131
1153
                                      DISPC_VID_ACCU0(1) };
 
1154
        u8 hor_start, hor_end, vert_start, vert_end;
1132
1155
 
1133
1156
        BUG_ON(plane == OMAP_DSS_GFX);
1134
1157
 
1135
 
        val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
 
1158
        dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
 
1159
        dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
 
1160
 
 
1161
        val = FLD_VAL(vaccu, vert_start, vert_end) |
 
1162
                        FLD_VAL(haccu, hor_start, hor_end);
 
1163
 
1136
1164
        dispc_write_reg(ac0_reg[plane-1], val);
1137
1165
}
1138
1166
 
1141
1169
        u32 val;
1142
1170
        const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
1143
1171
                                      DISPC_VID_ACCU1(1) };
 
1172
        u8 hor_start, hor_end, vert_start, vert_end;
1144
1173
 
1145
1174
        BUG_ON(plane == OMAP_DSS_GFX);
1146
1175
 
1147
 
        val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
 
1176
        dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
 
1177
        dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
 
1178
 
 
1179
        val = FLD_VAL(vaccu, vert_start, vert_end) |
 
1180
                        FLD_VAL(haccu, hor_start, hor_end);
 
1181
 
1148
1182
        dispc_write_reg(ac1_reg[plane-1], val);
1149
1183
}
1150
1184
 
1182
1216
        _dispc_set_fir(plane, fir_hinc, fir_vinc);
1183
1217
 
1184
1218
        l = dispc_read_reg(dispc_reg_att[plane]);
1185
 
        l &= ~((0x0f << 5) | (0x3 << 21));
1186
1219
 
 
1220
        /* RESIZEENABLE and VERTICALTAPS */
 
1221
        l &= ~((0x3 << 5) | (0x1 << 21));
1187
1222
        l |= fir_hinc ? (1 << 5) : 0;
1188
1223
        l |= fir_vinc ? (1 << 6) : 0;
1189
 
 
1190
 
        l |= hscaleup ? 0 : (1 << 7);
1191
 
        l |= vscaleup ? 0 : (1 << 8);
1192
 
 
1193
1224
        l |= five_taps ? (1 << 21) : 0;
1194
 
        l |= five_taps ? (1 << 22) : 0;
 
1225
 
 
1226
        /* VRESIZECONF and HRESIZECONF */
 
1227
        if (dss_has_feature(FEAT_RESIZECONF)) {
 
1228
                l &= ~(0x3 << 7);
 
1229
                l |= hscaleup ? 0 : (1 << 7);
 
1230
                l |= vscaleup ? 0 : (1 << 8);
 
1231
        }
 
1232
 
 
1233
        /* LINEBUFFERSPLIT */
 
1234
        if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
 
1235
                l &= ~(0x1 << 22);
 
1236
                l |= five_taps ? (1 << 22) : 0;
 
1237
        }
1195
1238
 
1196
1239
        dispc_write_reg(dispc_reg_att[plane], l);
1197
1240
 
1215
1258
static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1216
1259
                bool mirroring, enum omap_color_mode color_mode)
1217
1260
{
 
1261
        bool row_repeat = false;
 
1262
        int vidrot = 0;
 
1263
 
1218
1264
        if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1219
1265
                        color_mode == OMAP_DSS_COLOR_UYVY) {
1220
 
                int vidrot = 0;
1221
1266
 
1222
1267
                if (mirroring) {
1223
1268
                        switch (rotation) {
1251
1296
                        }
1252
1297
                }
1253
1298
 
1254
 
                REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1255
 
 
1256
1299
                if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1257
 
                        REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
 
1300
                        row_repeat = true;
1258
1301
                else
1259
 
                        REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
1260
 
        } else {
1261
 
                REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1262
 
                REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
 
1302
                        row_repeat = false;
1263
1303
        }
 
1304
 
 
1305
        REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
 
1306
        if (dss_has_feature(FEAT_ROWREPEATENABLE))
 
1307
                REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18);
1264
1308
}
1265
1309
 
1266
1310
static int color_mode_to_bpp(enum omap_color_mode color_mode)
2293
2337
        BUG_ON(pck_div < 2);
2294
2338
 
2295
2339
        enable_clocks(1);
2296
 
        dispc_write_reg(DISPC_DIVISOR(channel),
 
2340
        dispc_write_reg(DISPC_DIVISORo(channel),
2297
2341
                        FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2298
2342
        enable_clocks(0);
2299
2343
}
2302
2346
                int *pck_div)
2303
2347
{
2304
2348
        u32 l;
2305
 
        l = dispc_read_reg(DISPC_DIVISOR(channel));
 
2349
        l = dispc_read_reg(DISPC_DIVISORo(channel));
2306
2350
        *lck_div = FLD_GET(l, 23, 16);
2307
2351
        *pck_div = FLD_GET(l, 7, 0);
2308
2352
}
2311
2355
{
2312
2356
        unsigned long r = 0;
2313
2357
 
2314
 
        if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
2315
 
                r = dss_clk_get_rate(DSS_CLK_FCK1);
2316
 
        else
2317
 
#ifdef CONFIG_OMAP2_DSS_DSI
2318
 
                r = dsi_get_dsi1_pll_rate();
2319
 
#else
2320
 
        BUG();
2321
 
#endif
 
2358
        switch (dss_get_dispc_clk_source()) {
 
2359
        case DSS_CLK_SRC_FCK:
 
2360
                r = dss_clk_get_rate(DSS_CLK_FCK);
 
2361
                break;
 
2362
        case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 
2363
                r = dsi_get_pll_hsdiv_dispc_rate();
 
2364
                break;
 
2365
        default:
 
2366
                BUG();
 
2367
        }
 
2368
 
2322
2369
        return r;
2323
2370
}
2324
2371
 
2328
2375
        unsigned long r;
2329
2376
        u32 l;
2330
2377
 
2331
 
        l = dispc_read_reg(DISPC_DIVISOR(channel));
 
2378
        l = dispc_read_reg(DISPC_DIVISORo(channel));
2332
2379
 
2333
2380
        lcd = FLD_GET(l, 23, 16);
2334
2381
 
2335
 
        r = dispc_fclk_rate();
 
2382
        switch (dss_get_lcd_clk_source(channel)) {
 
2383
        case DSS_CLK_SRC_FCK:
 
2384
                r = dss_clk_get_rate(DSS_CLK_FCK);
 
2385
                break;
 
2386
        case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 
2387
                r = dsi_get_pll_hsdiv_dispc_rate();
 
2388
                break;
 
2389
        default:
 
2390
                BUG();
 
2391
        }
2336
2392
 
2337
2393
        return r / lcd;
2338
2394
}
2339
2395
 
2340
2396
unsigned long dispc_pclk_rate(enum omap_channel channel)
2341
2397
{
2342
 
        int lcd, pcd;
 
2398
        int pcd;
2343
2399
        unsigned long r;
2344
2400
        u32 l;
2345
2401
 
2346
 
        l = dispc_read_reg(DISPC_DIVISOR(channel));
 
2402
        l = dispc_read_reg(DISPC_DIVISORo(channel));
2347
2403
 
2348
 
        lcd = FLD_GET(l, 23, 16);
2349
2404
        pcd = FLD_GET(l, 7, 0);
2350
2405
 
2351
 
        r = dispc_fclk_rate();
 
2406
        r = dispc_lclk_rate(channel);
2352
2407
 
2353
 
        return r / lcd / pcd;
 
2408
        return r / pcd;
2354
2409
}
2355
2410
 
2356
2411
void dispc_dump_clocks(struct seq_file *s)
2357
2412
{
2358
2413
        int lcd, pcd;
 
2414
        u32 l;
 
2415
        enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
 
2416
        enum dss_clk_source lcd_clk_src;
2359
2417
 
2360
2418
        enable_clocks(1);
2361
2419
 
2362
2420
        seq_printf(s, "- DISPC -\n");
2363
2421
 
2364
 
        seq_printf(s, "dispc fclk source = %s\n",
2365
 
                        dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
2366
 
                        "dss1_alwon_fclk" : "dsi1_pll_fclk");
 
2422
        seq_printf(s, "dispc fclk source = %s (%s)\n",
 
2423
                        dss_get_generic_clk_source_name(dispc_clk_src),
 
2424
                        dss_feat_get_clk_source_name(dispc_clk_src));
2367
2425
 
2368
2426
        seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2369
2427
 
 
2428
        if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
 
2429
                seq_printf(s, "- DISPC-CORE-CLK -\n");
 
2430
                l = dispc_read_reg(DISPC_DIVISOR);
 
2431
                lcd = FLD_GET(l, 23, 16);
 
2432
 
 
2433
                seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
 
2434
                                (dispc_fclk_rate()/lcd), lcd);
 
2435
        }
2370
2436
        seq_printf(s, "- LCD1 -\n");
2371
2437
 
 
2438
        lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
 
2439
 
 
2440
        seq_printf(s, "lcd1_clk source = %s (%s)\n",
 
2441
                dss_get_generic_clk_source_name(lcd_clk_src),
 
2442
                dss_feat_get_clk_source_name(lcd_clk_src));
 
2443
 
2372
2444
        dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2373
2445
 
2374
2446
        seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2378
2450
        if (dss_has_feature(FEAT_MGR_LCD2)) {
2379
2451
                seq_printf(s, "- LCD2 -\n");
2380
2452
 
 
2453
                lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
 
2454
 
 
2455
                seq_printf(s, "lcd2_clk source = %s (%s)\n",
 
2456
                        dss_get_generic_clk_source_name(lcd_clk_src),
 
2457
                        dss_feat_get_clk_source_name(lcd_clk_src));
 
2458
 
2381
2459
                dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2382
2460
 
2383
2461
                seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2440
2518
{
2441
2519
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
2442
2520
 
2443
 
        dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
2521
        dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
2444
2522
 
2445
2523
        DUMPREG(DISPC_REVISION);
2446
2524
        DUMPREG(DISPC_SYSCONFIG);
2459
2537
        DUMPREG(DISPC_TIMING_H(0));
2460
2538
        DUMPREG(DISPC_TIMING_V(0));
2461
2539
        DUMPREG(DISPC_POL_FREQ(0));
2462
 
        DUMPREG(DISPC_DIVISOR(0));
 
2540
        DUMPREG(DISPC_DIVISORo(0));
2463
2541
        DUMPREG(DISPC_GLOBAL_ALPHA);
2464
2542
        DUMPREG(DISPC_SIZE_DIG);
2465
2543
        DUMPREG(DISPC_SIZE_LCD(0));
2471
2549
                DUMPREG(DISPC_TIMING_H(2));
2472
2550
                DUMPREG(DISPC_TIMING_V(2));
2473
2551
                DUMPREG(DISPC_POL_FREQ(2));
2474
 
                DUMPREG(DISPC_DIVISOR(2));
 
2552
                DUMPREG(DISPC_DIVISORo(2));
2475
2553
                DUMPREG(DISPC_SIZE_LCD(2));
2476
2554
        }
2477
2555
 
2597
2675
        DUMPREG(DISPC_VID_PRELOAD(0));
2598
2676
        DUMPREG(DISPC_VID_PRELOAD(1));
2599
2677
 
2600
 
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
2678
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
2601
2679
#undef DUMPREG
2602
2680
}
2603
2681
 
2713
2791
 
2714
2792
        fck = dispc_fclk_rate();
2715
2793
 
2716
 
        cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16);
2717
 
        cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0);
 
2794
        cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
 
2795
        cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
2718
2796
 
2719
2797
        cinfo->lck = fck / cinfo->lck_div;
2720
2798
        cinfo->pck = cinfo->lck / cinfo->pck_div;
2791
2869
                break;
2792
2870
        }
2793
2871
 
 
2872
        if (ret)
 
2873
                goto err;
 
2874
 
2794
2875
        _omap_dispc_set_irqs();
2795
2876
 
2796
2877
        spin_unlock_irqrestore(&dispc.irq_lock, flags);
2866
2947
 * but we presume they are on because we got an IRQ. However,
2867
2948
 * an irq handler may turn the clocks off, so we may not have
2868
2949
 * clock later in the function. */
2869
 
void dispc_irq_handler(void)
 
2950
static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
2870
2951
{
2871
2952
        int i;
2872
 
        u32 irqstatus;
 
2953
        u32 irqstatus, irqenable;
2873
2954
        u32 handledirqs = 0;
2874
2955
        u32 unhandled_errors;
2875
2956
        struct omap_dispc_isr_data *isr_data;
2878
2959
        spin_lock(&dispc.irq_lock);
2879
2960
 
2880
2961
        irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
 
2962
        irqenable = dispc_read_reg(DISPC_IRQENABLE);
 
2963
 
 
2964
        /* IRQ is not for us */
 
2965
        if (!(irqstatus & irqenable)) {
 
2966
                spin_unlock(&dispc.irq_lock);
 
2967
                return IRQ_NONE;
 
2968
        }
2881
2969
 
2882
2970
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2883
2971
        spin_lock(&dispc.irq_stats_lock);
2929
3017
        }
2930
3018
 
2931
3019
        spin_unlock(&dispc.irq_lock);
 
3020
 
 
3021
        return IRQ_HANDLED;
2932
3022
}
2933
3023
 
2934
3024
static void dispc_error_worker(struct work_struct *work)
3253
3343
        l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
3254
3344
        dispc_write_reg(DISPC_SYSCONFIG, l);
3255
3345
 
 
3346
        /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
 
3347
        if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
 
3348
                l = dispc_read_reg(DISPC_DIVISOR);
 
3349
                /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
 
3350
                l = FLD_MOD(l, 1, 0, 0);
 
3351
                l = FLD_MOD(l, 1, 23, 16);
 
3352
                dispc_write_reg(DISPC_DIVISOR, l);
 
3353
        }
 
3354
 
3256
3355
        /* FUNCGATED */
3257
3356
        if (dss_has_feature(FEAT_FUNCGATED))
3258
3357
                REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3269
3368
        dispc_read_plane_fifo_sizes();
3270
3369
}
3271
3370
 
3272
 
int dispc_init(void)
3273
 
{
3274
 
        u32 rev;
3275
 
 
3276
 
        spin_lock_init(&dispc.irq_lock);
3277
 
 
3278
 
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3279
 
        spin_lock_init(&dispc.irq_stats_lock);
3280
 
        dispc.irq_stats.last_reset = jiffies;
3281
 
#endif
3282
 
 
3283
 
        INIT_WORK(&dispc.error_work, dispc_error_worker);
3284
 
 
3285
 
        dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
3286
 
        if (!dispc.base) {
3287
 
                DSSERR("can't ioremap DISPC\n");
3288
 
                return -ENOMEM;
3289
 
        }
3290
 
 
3291
 
        enable_clocks(1);
3292
 
 
3293
 
        _omap_dispc_initial_config();
3294
 
 
3295
 
        _omap_dispc_initialize_irq();
3296
 
 
3297
 
        dispc_save_context();
3298
 
 
3299
 
        rev = dispc_read_reg(DISPC_REVISION);
3300
 
        printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
3301
 
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3302
 
 
3303
 
        enable_clocks(0);
3304
 
 
3305
 
        return 0;
3306
 
}
3307
 
 
3308
 
void dispc_exit(void)
3309
 
{
3310
 
        iounmap(dispc.base);
3311
 
}
3312
 
 
3313
3371
int dispc_enable_plane(enum omap_plane plane, bool enable)
3314
3372
{
3315
3373
        DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3359
3417
 
3360
3418
        return r;
3361
3419
}
 
3420
 
 
3421
/* DISPC HW IP initialisation */
 
3422
static int omap_dispchw_probe(struct platform_device *pdev)
 
3423
{
 
3424
        u32 rev;
 
3425
        int r = 0;
 
3426
        struct resource *dispc_mem;
 
3427
 
 
3428
        dispc.pdev = pdev;
 
3429
 
 
3430
        spin_lock_init(&dispc.irq_lock);
 
3431
 
 
3432
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 
3433
        spin_lock_init(&dispc.irq_stats_lock);
 
3434
        dispc.irq_stats.last_reset = jiffies;
 
3435
#endif
 
3436
 
 
3437
        INIT_WORK(&dispc.error_work, dispc_error_worker);
 
3438
 
 
3439
        dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
 
3440
        if (!dispc_mem) {
 
3441
                DSSERR("can't get IORESOURCE_MEM DISPC\n");
 
3442
                r = -EINVAL;
 
3443
                goto fail0;
 
3444
        }
 
3445
        dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
 
3446
        if (!dispc.base) {
 
3447
                DSSERR("can't ioremap DISPC\n");
 
3448
                r = -ENOMEM;
 
3449
                goto fail0;
 
3450
        }
 
3451
        dispc.irq = platform_get_irq(dispc.pdev, 0);
 
3452
        if (dispc.irq < 0) {
 
3453
                DSSERR("platform_get_irq failed\n");
 
3454
                r = -ENODEV;
 
3455
                goto fail1;
 
3456
        }
 
3457
 
 
3458
        r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
 
3459
                "OMAP DISPC", dispc.pdev);
 
3460
        if (r < 0) {
 
3461
                DSSERR("request_irq failed\n");
 
3462
                goto fail1;
 
3463
        }
 
3464
 
 
3465
        enable_clocks(1);
 
3466
 
 
3467
        _omap_dispc_initial_config();
 
3468
 
 
3469
        _omap_dispc_initialize_irq();
 
3470
 
 
3471
        dispc_save_context();
 
3472
 
 
3473
        rev = dispc_read_reg(DISPC_REVISION);
 
3474
        dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
 
3475
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
3476
 
 
3477
        enable_clocks(0);
 
3478
 
 
3479
        return 0;
 
3480
fail1:
 
3481
        iounmap(dispc.base);
 
3482
fail0:
 
3483
        return r;
 
3484
}
 
3485
 
 
3486
static int omap_dispchw_remove(struct platform_device *pdev)
 
3487
{
 
3488
        free_irq(dispc.irq, dispc.pdev);
 
3489
        iounmap(dispc.base);
 
3490
        return 0;
 
3491
}
 
3492
 
 
3493
static struct platform_driver omap_dispchw_driver = {
 
3494
        .probe          = omap_dispchw_probe,
 
3495
        .remove         = omap_dispchw_remove,
 
3496
        .driver         = {
 
3497
                .name   = "omapdss_dispc",
 
3498
                .owner  = THIS_MODULE,
 
3499
        },
 
3500
};
 
3501
 
 
3502
int dispc_init_platform_driver(void)
 
3503
{
 
3504
        return platform_driver_register(&omap_dispchw_driver);
 
3505
}
 
3506
 
 
3507
void dispc_uninit_platform_driver(void)
 
3508
{
 
3509
        return platform_driver_unregister(&omap_dispchw_driver);
 
3510
}