Subversion Repositories Kolibri OS

Rev

Rev 2340 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2338 Serge 1
#include "drmP.h"
2
#include "drm.h"
3
#include "i915_drm.h"
4
#include "i915_drv.h"
5
#include "intel_drv.h"
6
 
7
 
8
#include 
9
#include 
10
#include 
11
#include 
12
#include 
13
 
14
#include 
15
 
16
typedef struct tag_object  kobj_t;
17
typedef struct tag_display display_t;
18
 
19
struct tag_object
20
{
21
    uint32_t   magic;
22
    void      *destroy;
23
    kobj_t    *fd;
24
    kobj_t    *bk;
25
    uint32_t   pid;
26
};
27
 
28
typedef struct
29
{
30
    kobj_t     header;
31
 
32
    uint32_t  *data;
33
    uint32_t   hot_x;
34
    uint32_t   hot_y;
35
 
36
    struct list_head   list;
37
    struct drm_i915_gem_object  *cobj;
38
}cursor_t;
39
 
40
#define CURSOR_WIDTH 64
41
#define CURSOR_HEIGHT 64
42
 
43
 
44
struct tag_display
45
{
46
    int  x;
47
    int  y;
48
    int  width;
49
    int  height;
50
    int  bpp;
51
    int  vrefresh;
52
    int  pitch;
53
    int  lfb;
54
 
55
    int  supported_modes;
56
    struct drm_device    *ddev;
57
    struct drm_connector *connector;
58
    struct drm_crtc      *crtc;
59
 
60
    struct list_head   cursors;
61
 
62
    cursor_t   *cursor;
63
    int       (*init_cursor)(cursor_t*);
64
    cursor_t* (__stdcall *select_cursor)(cursor_t*);
65
    void      (*show_cursor)(int show);
66
    void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
67
    void      (__stdcall *restore_cursor)(int x, int y);
68
    void      (*disable_mouse)(void);
69
};
70
 
71
 
72
static display_t *os_display;
73
 
74
int init_cursor(cursor_t *cursor);
75
static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
76
static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
77
 
78
void __stdcall restore_cursor(int x, int y)
79
{};
80
 
81
void disable_mouse(void)
82
{};
83
 
84
static int count_connector_modes(struct drm_connector* connector)
85
{
86
    struct drm_display_mode  *mode;
87
    int count = 0;
88
 
89
    list_for_each_entry(mode, &connector->modes, head)
90
    {
91
        count++;
92
    };
93
    return count;
94
};
95
 
96
int init_display_kms(struct drm_device *dev)
97
{
98
    struct drm_connector    *connector;
99
    struct drm_connector_helper_funcs *connector_funcs;
100
    struct drm_encoder      *encoder;
101
    struct drm_crtc         *crtc = NULL;
102
    struct drm_framebuffer  *fb;
103
 
104
    cursor_t  *cursor;
105
    u32_t      ifl;
106
 
107
    ENTER();
108
 
109
    list_for_each_entry(connector, &dev->mode_config.connector_list, head)
110
    {
111
        if( connector->status != connector_status_connected)
112
            continue;
113
 
114
        connector_funcs = connector->helper_private;
115
        encoder = connector_funcs->best_encoder(connector);
116
        if( encoder == NULL)
117
        {
118
            dbgprintf("CONNECTOR %x ID: %d no active encoders\n",
119
                      connector, connector->base.id);
120
            continue;
121
        }
122
        connector->encoder = encoder;
123
 
124
        dbgprintf("CONNECTOR %x ID:  %d status %d encoder %x\n crtc %x\n",
125
               connector, connector->base.id,
126
               connector->status, connector->encoder,
127
               encoder->crtc);
128
 
129
        crtc = encoder->crtc;
130
        break;
131
    };
132
 
133
    if(connector == NULL)
134
    {
135
        dbgprintf("No active connectors!\n");
136
        return -1;
137
    };
138
 
139
    if(crtc == NULL)
140
    {
141
        struct drm_crtc *tmp_crtc;
142
        int crtc_mask = 1;
143
 
144
        list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
145
        {
146
            if (encoder->possible_crtcs & crtc_mask)
147
            {
148
                crtc = tmp_crtc;
149
                encoder->crtc = crtc;
150
                break;
151
            };
152
            crtc_mask <<= 1;
153
        };
154
    };
155
 
156
    if(crtc == NULL)
157
    {
158
        dbgprintf("No CRTC for encoder %d\n", encoder->base.id);
159
        return -1;
160
    };
161
 
162
 
163
    DRM_DEBUG_KMS("[Select CRTC:%d]\n", crtc->base.id);
164
 
165
    os_display = GetDisplay();
166
 
167
    os_display->ddev = dev;
168
    os_display->connector = connector;
169
    os_display->crtc = crtc;
170
 
171
    os_display->supported_modes = count_connector_modes(connector);
172
 
173
 
174
    ifl = safe_cli();
175
    {
176
        struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
177
 
178
        list_for_each_entry(cursor, &os_display->cursors, list)
179
        {
180
            init_cursor(cursor);
181
        };
182
 
183
        os_display->restore_cursor(0,0);
184
        os_display->init_cursor    = init_cursor;
185
        os_display->select_cursor  = select_cursor_kms;
186
        os_display->show_cursor    = NULL;
187
        os_display->move_cursor    = move_cursor_kms;
188
        os_display->restore_cursor = restore_cursor;
189
        os_display->disable_mouse  = disable_mouse;
190
 
191
        intel_crtc->cursor_x = os_display->width/2;
192
        intel_crtc->cursor_y = os_display->height/2;
193
 
194
        select_cursor_kms(os_display->cursor);
195
    };
196
    safe_sti(ifl);
197
 
198
 
199
    LEAVE();
200
 
201
    return 0;
202
};
203
 
204
 
205
bool set_mode(struct drm_device *dev, struct drm_connector *connector,
206
              videomode_t *reqmode, bool strict)
207
{
208
    struct drm_display_mode  *mode = NULL, *tmpmode;
209
    drm_i915_private_t *dev_priv = dev->dev_private;
210
    struct drm_fb_helper *fb_helper = &dev_priv->fbdev->helper;
211
 
212
    bool ret = false;
213
 
214
    ENTER();
215
 
216
    dbgprintf("width %d height %d vrefresh %d\n",
217
               reqmode->width, reqmode->height, reqmode->freq);
218
 
219
    list_for_each_entry(tmpmode, &connector->modes, head)
220
    {
221
        if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
222
            (drm_mode_height(tmpmode)   == reqmode->height) &&
223
            (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
224
        {
225
            mode = tmpmode;
226
            goto do_set;
227
        }
228
    };
229
 
230
    if( (mode == NULL) && (strict == false) )
231
    {
232
        list_for_each_entry(tmpmode, &connector->modes, head)
233
        {
234
            if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
235
                (drm_mode_height(tmpmode) == reqmode->height) )
236
            {
237
                mode = tmpmode;
238
                goto do_set;
239
            }
240
        };
241
    };
242
 
243
do_set:
244
 
245
    if( mode != NULL )
246
    {
247
        struct drm_framebuffer   *fb;
248
        struct drm_encoder       *encoder;
249
        struct drm_crtc          *crtc;
250
 
251
        char *con_name;
252
        char *enc_name;
253
 
254
        encoder = connector->encoder;
255
        crtc = encoder->crtc;
256
 
257
        con_name = drm_get_connector_name(connector);
258
        enc_name = drm_get_encoder_name(encoder);
259
 
260
        dbgprintf("set mode %d %d connector %s encoder %s\n",
261
                   reqmode->width, reqmode->height, con_name, enc_name);
262
 
263
        fb = fb_helper->fb;
264
 
265
        fb->width  = reqmode->width;
266
        fb->height = reqmode->height;
267
        fb->pitch  = ALIGN(reqmode->width * 4, 64);
268
        fb->bits_per_pixel = 32;
269
        fb->depth == 24;
270
 
271
        crtc->fb = fb;
272
        crtc->enabled = true;
273
        os_display->crtc = crtc;
274
 
275
        ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
276
 
277
//        select_cursor_kms(rdisplay->cursor);
278
//        radeon_show_cursor_kms(crtc);
279
 
280
        if (ret == true)
281
        {
282
            os_display->width    = fb->width;
283
            os_display->height   = fb->height;
284
            os_display->pitch    = fb->pitch;
285
            os_display->vrefresh = drm_mode_vrefresh(mode);
286
 
287
            sysSetScreen(fb->width, fb->height, fb->pitch);
288
 
289
            dbgprintf("new mode %d x %d pitch %d\n",
290
                       fb->width, fb->height, fb->pitch);
291
        }
292
        else
293
            DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
294
                       fb->width, fb->height, crtc);
295
    }
296
 
297
    LEAVE();
298
    return ret;
299
};
300
 
301
 
302
 
303
int get_videomodes(videomode_t *mode, int *count)
304
{
305
    int err = -1;
306
 
307
    ENTER();
308
 
309
    dbgprintf("mode %x count %d\n", mode, *count);
310
 
311
    if( *count == 0 )
312
    {
313
        *count = os_display->supported_modes;
314
        err = 0;
315
    }
316
    else if( mode != NULL )
317
    {
318
        struct drm_display_mode  *drmmode;
319
        int i = 0;
320
 
321
        if( *count > os_display->supported_modes)
322
            *count = os_display->supported_modes;
323
 
324
        list_for_each_entry(drmmode, &os_display->connector->modes, head)
325
        {
326
            if( i < *count)
327
            {
328
                mode->width  = drm_mode_width(drmmode);
329
                mode->height = drm_mode_height(drmmode);
330
                mode->bpp    = 32;
331
                mode->freq   = drm_mode_vrefresh(drmmode);
332
                i++;
333
                mode++;
334
            }
335
            else break;
336
        };
337
        *count = i;
338
        err = 0;
339
    };
340
    LEAVE();
341
    return err;
342
};
343
 
344
int set_user_mode(videomode_t *mode)
345
{
346
    int err = -1;
347
 
348
    ENTER();
349
 
350
    dbgprintf("width %d height %d vrefresh %d\n",
351
               mode->width, mode->height, mode->freq);
352
 
353
    if( (mode->width  != 0)  &&
354
        (mode->height != 0)  &&
355
        (mode->freq   != 0 ) &&
356
        ( (mode->width   != os_display->width)  ||
357
          (mode->height  != os_display->height) ||
358
          (mode->freq    != os_display->vrefresh) ) )
359
    {
360
        if( set_mode(os_display->ddev, os_display->connector, mode, true) )
361
            err = 0;
362
    };
363
 
364
    LEAVE();
365
    return err;
366
};
367
 
368
void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor)
369
{
370
    list_del(&cursor->list);
371
//    radeon_bo_unpin(cursor->robj);
372
//    KernelFree(cursor->data);
373
    __DestroyObject(cursor);
374
};
375
 
376
int init_cursor(cursor_t *cursor)
377
{
378
    struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
379
    struct drm_i915_gem_object *obj;
380
    uint32_t *bits;
381
    uint32_t *src;
382
 
383
    int       i,j;
384
    int       ret;
385
 
386
    ENTER();
387
 
388
    if (dev_priv->info->cursor_needs_physical)
389
    {
390
        bits = (uint32_t*)KernelAlloc(CURSOR_WIDTH*CURSOR_HEIGHT*4);
391
        if (unlikely(bits == NULL))
392
            return ENOMEM;
393
        cursor->cobj = (struct drm_i915_gem_object *)GetPgAddr(bits);
394
    }
395
    else
396
    {
397
        obj = i915_gem_alloc_object(os_display->ddev, CURSOR_WIDTH*CURSOR_HEIGHT*4);
398
        if (unlikely(obj == NULL))
399
            return -ENOMEM;
400
 
401
        ret = i915_gem_object_pin(obj, CURSOR_WIDTH*CURSOR_HEIGHT*4, true);
402
        if (ret) {
403
//           drm_gem_object_unreference(&obj->base);
404
            return ret;
405
        }
406
 
407
/* You don't need to worry about fragmentation issues.
408
 * GTT space is continuous. I guarantee it.                           */
409
 
410
        bits = (u32*)MapIoMem(get_bus_addr() + obj->gtt_offset,
411
                    CURSOR_WIDTH*CURSOR_HEIGHT*4, PG_SW);
412
 
413
        if (unlikely(bits == NULL))
414
        {
415
//          i915_gem_object_unpin(obj);
416
//           drm_gem_object_unreference(&obj->base);
417
            return -ENOMEM;
418
        };
419
        cursor->cobj = obj;
420
    };
421
 
422
    src = cursor->data;
423
 
424
    for(i = 0; i < 32; i++)
425
    {
426
        for(j = 0; j < 32; j++)
427
            *bits++ = *src++;
428
        for(j = 32; j < CURSOR_WIDTH; j++)
429
            *bits++ = 0;
430
    }
431
    for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++)
432
        *bits++ = 0;
433
 
434
// release old cursor
435
 
436
//    KernelFree(cursor->data);
437
 
438
    cursor->data = bits;
439
 
440
    cursor->header.destroy = destroy_cursor;
441
    LEAVE();
442
 
443
    return 0;
444
}
445
 
446
 
447
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
448
{
449
    struct drm_device *dev = crtc->dev;
450
    struct drm_i915_private *dev_priv = dev->dev_private;
451
    struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
452
    int pipe = intel_crtc->pipe;
453
    bool visible = base != 0;
454
 
455
    if (intel_crtc->cursor_visible != visible) {
456
        uint32_t cntl = I915_READ(CURCNTR(pipe));
457
        if (base) {
458
            cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
459
            cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
460
            cntl |= pipe << 28; /* Connect to correct pipe */
461
        } else {
462
            cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
463
            cntl |= CURSOR_MODE_DISABLE;
464
        }
465
        I915_WRITE(CURCNTR(pipe), cntl);
466
 
467
        intel_crtc->cursor_visible = visible;
468
    }
469
    /* and commit changes on next vblank */
470
    I915_WRITE(CURBASE(pipe), base);
471
}
472
 
473
void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
474
{
475
    struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
476
    struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
477
    u32 base, pos;
478
    bool visible;
479
 
480
    int pipe = intel_crtc->pipe;
481
 
482
    intel_crtc->cursor_x = x;
483
    intel_crtc->cursor_y = y;
484
 
485
    x = x - cursor->hot_x;
486
    y = y - cursor->hot_y;
487
 
488
 
489
    pos = 0;
490
 
491
    base = intel_crtc->cursor_addr;
492
    if (x >= os_display->width)
493
        base = 0;
494
 
495
    if (y >= os_display->height)
496
        base = 0;
497
 
498
    if (x < 0)
499
    {
500
        if (x + intel_crtc->cursor_width < 0)
501
            base = 0;
502
 
503
        pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
504
        x = -x;
505
    }
506
    pos |= x << CURSOR_X_SHIFT;
507
 
508
    if (y < 0)
509
    {
510
        if (y + intel_crtc->cursor_height < 0)
511
            base = 0;
512
 
513
        pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
514
        y = -y;
515
    }
516
    pos |= y << CURSOR_Y_SHIFT;
517
 
518
    visible = base != 0;
519
    if (!visible && !intel_crtc->cursor_visible)
520
        return;
521
 
522
    I915_WRITE(CURPOS(pipe), pos);
523
//    if (IS_845G(dev) || IS_I865G(dev))
524
//        i845_update_cursor(crtc, base);
525
//    else
526
        i9xx_update_cursor(os_display->crtc, base);
527
 
528
};
529
 
530
 
531
cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
532
{
533
    struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
534
    struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
535
    cursor_t *old;
536
 
537
    old = os_display->cursor;
538
    os_display->cursor = cursor;
539
 
540
    if (!dev_priv->info->cursor_needs_physical)
541
       intel_crtc->cursor_addr = cursor->cobj->gtt_offset;
542
    else
543
        intel_crtc->cursor_addr = cursor->cobj;
544
 
545
    intel_crtc->cursor_width = 32;
546
    intel_crtc->cursor_height = 32;
547
 
548
    move_cursor_kms(cursor, intel_crtc->cursor_x, intel_crtc->cursor_y);
549
    return old;
550
};
551
 
552
#if 0
553
static void intel_crtc_update_cursor(struct drm_crtc *crtc,
554
                     bool on)
555
{
556
    struct drm_device *dev = crtc->dev;
557
    struct drm_i915_private *dev_priv = dev->dev_private;
558
    struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
559
    int pipe = intel_crtc->pipe;
560
    int x = intel_crtc->cursor_x;
561
    int y = intel_crtc->cursor_y;
562
    u32 base, pos;
563
    bool visible;
564
 
565
    pos = 0;
566
 
567
    if (on && crtc->enabled && crtc->fb) {
568
        base = intel_crtc->cursor_addr;
569
        if (x > (int) crtc->fb->width)
570
            base = 0;
571
 
572
        if (y > (int) crtc->fb->height)
573
            base = 0;
574
    } else
575
        base = 0;
576
 
577
    if (x < 0) {
578
        if (x + intel_crtc->cursor_width < 0)
579
            base = 0;
580
 
581
        pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
582
        x = -x;
583
    }
584
    pos |= x << CURSOR_X_SHIFT;
585
 
586
    if (y < 0) {
587
        if (y + intel_crtc->cursor_height < 0)
588
            base = 0;
589
 
590
        pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
591
        y = -y;
592
    }
593
    pos |= y << CURSOR_Y_SHIFT;
594
 
595
    visible = base != 0;
596
    if (!visible && !intel_crtc->cursor_visible)
597
        return;
598
 
599
    I915_WRITE(CURPOS(pipe), pos);
600
    if (IS_845G(dev) || IS_I865G(dev))
601
        i845_update_cursor(crtc, base);
602
    else
603
        i9xx_update_cursor(crtc, base);
604
 
605
    if (visible)
606
        intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
607
}
608
 
609
#endif
610