1f29dbc25Smrg/*
2f29dbc25Smrg * Copyright (c) 2007 Advanced Micro Devices, Inc.
3f29dbc25Smrg *
4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"),
6f29dbc25Smrg * to deal in the Software without restriction, including without limitation
7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the
9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions:
10f29dbc25Smrg *
11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
12f29dbc25Smrg * all copies or substantial portions of the Software.
13f29dbc25Smrg *
14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20f29dbc25Smrg * DEALINGS IN THE SOFTWARE.
21f29dbc25Smrg *
22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
24f29dbc25Smrg * software without specific prior written permission.
25f29dbc25Smrg */
26f29dbc25Smrg
27f29dbc25Smrg/* We want to share as much code between GX and LX as we possibly can for obvious reasons */
28f29dbc25Smrg
29f29dbc25Smrg#ifdef HAVE_CONFIG_H
30f29dbc25Smrg#include "config.h"
31f29dbc25Smrg#endif
32f29dbc25Smrg
3304007ebaSmrg#include <string.h>             /* memcmp() */
34f29dbc25Smrg#include <unistd.h>
35f29dbc25Smrg#include <sys/types.h>
36f29dbc25Smrg#include <sys/stat.h>
37f29dbc25Smrg#include <fcntl.h>
38f29dbc25Smrg#include <sys/ioctl.h>
39f29dbc25Smrg
4000be8644Schristos#include "xorg-server.h"
41f29dbc25Smrg#include "xf86.h"
42f29dbc25Smrg#include "geode.h"
43f29dbc25Smrg
44f29dbc25Smrg#define move0(d,s,n) \
45f29dbc25Smrg  __asm__ __volatile__( \
46f29dbc25Smrg  "   rep; movsl\n" \
47f29dbc25Smrg  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
48f29dbc25Smrg  : "0" (n), "1" (s), "2" (d) \
49f29dbc25Smrg  : "memory")
50f29dbc25Smrg
51f29dbc25Smrg#define move1(d,s,n) \
52f29dbc25Smrg  __asm__ __volatile__( \
53f29dbc25Smrg  "   rep; movsl\n" \
54f29dbc25Smrg  "   movsb\n" \
55f29dbc25Smrg  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
56f29dbc25Smrg  : "0" (n), "1" (s), "2" (d) \
57f29dbc25Smrg  : "memory")
58f29dbc25Smrg
59f29dbc25Smrg#define move2(d,s,n) \
60f29dbc25Smrg  __asm__ __volatile__( \
61f29dbc25Smrg  "   rep; movsl\n" \
62f29dbc25Smrg  "   movsw\n" \
63f29dbc25Smrg  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
64f29dbc25Smrg  : "0" (n), "1" (s), "2" (d) \
65f29dbc25Smrg  : "memory")
66f29dbc25Smrg
67f29dbc25Smrg#define move3(d,s,n) \
68f29dbc25Smrg  __asm__ __volatile__( \
69f29dbc25Smrg  "   rep; movsl\n" \
70f29dbc25Smrg  "   movsw\n" \
71f29dbc25Smrg  "   movsb\n" \
72f29dbc25Smrg  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
73f29dbc25Smrg  : "0" (n), "1" (s), "2" (d) \
74f29dbc25Smrg  : "memory")
75f29dbc25Smrg
76f29dbc25Smrgvoid
77f29dbc25Smrggeode_memory_to_screen_blt(unsigned long src, unsigned long dst,
7804007ebaSmrg                           unsigned long sp, unsigned long dp, long w, long h,
7904007ebaSmrg                           int bpp)
80f29dbc25Smrg{
81f29dbc25Smrg    int d0, d1, d2;
82f29dbc25Smrg    int n = w * (bpp >> 3);
83f29dbc25Smrg    int m = n >> 2;
84f29dbc25Smrg
85f29dbc25Smrg    switch (n & 3) {
86f29dbc25Smrg    case 0:
8704007ebaSmrg        while (--h >= 0) {
8804007ebaSmrg            move0(dst, src, m);
8904007ebaSmrg            src += sp;
9004007ebaSmrg            dst += dp;
9104007ebaSmrg        }
9204007ebaSmrg        break;
93f29dbc25Smrg    case 1:
9404007ebaSmrg        while (--h >= 0) {
9504007ebaSmrg            move1(dst, src, m);
9604007ebaSmrg            src += sp;
9704007ebaSmrg            dst += dp;
9804007ebaSmrg        }
9904007ebaSmrg        break;
100f29dbc25Smrg    case 2:
10104007ebaSmrg        while (--h >= 0) {
10204007ebaSmrg            move2(dst, src, m);
10304007ebaSmrg            src += sp;
10404007ebaSmrg            dst += dp;
10504007ebaSmrg        }
10604007ebaSmrg        break;
107f29dbc25Smrg    case 3:
10804007ebaSmrg        while (--h >= 0) {
10904007ebaSmrg            move3(dst, src, m);
11004007ebaSmrg            src += sp;
11104007ebaSmrg            dst += dp;
11204007ebaSmrg        }
11304007ebaSmrg        break;
114f29dbc25Smrg    }
115f29dbc25Smrg}
116f29dbc25Smrg
117f29dbc25Smrg/* I borrowed this function from the i830 driver - its much better
118f29dbc25Smrg   then what we had before
119f29dbc25Smrg*/
120f29dbc25Smrg
121f29dbc25Smrgint
122f29dbc25SmrgGeodeGetRefreshRate(DisplayModePtr pMode)
123f29dbc25Smrg{
124f29dbc25Smrg    if (pMode->VRefresh)
12504007ebaSmrg        return (int) (pMode->VRefresh + 0.5);
126f29dbc25Smrg
12704007ebaSmrg    return (int) (pMode->Clock * 1000.0 / pMode->HTotal / pMode->VTotal + 0.5);
128f29dbc25Smrg}
129f29dbc25Smrg
130f29dbc25Smrg/* This is used by both GX and LX.  It could be accelerated for LX, probably, but
131f29dbc25Smrg   that would involve a two pass blt, the first to copy the data, and the second
132f29dbc25Smrg   to copy the grey (using a pattern).  That seems like a bit of work for a
133f29dbc25Smrg   very underused format - so we'll just use the slow version.
134f29dbc25Smrg*/
135f29dbc25Smrg
136f29dbc25Smrgvoid
137f29dbc25SmrgGeodeCopyGreyscale(unsigned char *src, unsigned char *dst,
13804007ebaSmrg                   int dstPitch, int srcPitch, int h, int w)
139f29dbc25Smrg{
140f29dbc25Smrg    int i;
141f29dbc25Smrg    unsigned char *src2 = src;
142f29dbc25Smrg    unsigned char *dst2 = dst;
143f29dbc25Smrg    unsigned char *dst3;
144f29dbc25Smrg    unsigned char *src3;
145f29dbc25Smrg
146f29dbc25Smrg    dstPitch <<= 1;
147f29dbc25Smrg
148f29dbc25Smrg    while (h--) {
14904007ebaSmrg        dst3 = dst2;
15004007ebaSmrg        src3 = src2;
15104007ebaSmrg        for (i = 0; i < w; i++) {
15204007ebaSmrg            *dst3++ = *src3++;  /* Copy Y data */
15304007ebaSmrg            *dst3++ = 0x80;     /* Fill UV with 0x80 - greyscale */
15404007ebaSmrg        }
15504007ebaSmrg
15604007ebaSmrg        src3 = src2;
15704007ebaSmrg        for (i = 0; i < w; i++) {
15804007ebaSmrg            *dst3++ = *src3++;  /* Copy Y data */
15904007ebaSmrg            *dst3++ = 0x80;     /* Fill UV with 0x80 - greyscale */
16004007ebaSmrg        }
16104007ebaSmrg
16204007ebaSmrg        dst2 += dstPitch;
16304007ebaSmrg        src2 += srcPitch;
164f29dbc25Smrg    }
165f29dbc25Smrg}
166f29dbc25Smrg
167f29dbc25Smrg#if defined(linux)
168f29dbc25Smrg
169f29dbc25Smrg#include <linux/fb.h>
170f29dbc25Smrg
171f29dbc25Smrgint
172f29dbc25SmrgGeodeGetSizeFromFB(unsigned int *size)
173f29dbc25Smrg{
174f29dbc25Smrg    struct fb_fix_screeninfo fix;
175f29dbc25Smrg    int ret;
176f29dbc25Smrg    int fd = open("/dev/fb0", O_RDONLY);
177f29dbc25Smrg
178f29dbc25Smrg    if (fd == -1)
17904007ebaSmrg        return -1;
180f29dbc25Smrg
181f29dbc25Smrg    ret = ioctl(fd, FBIOGET_FSCREENINFO, &fix);
182f29dbc25Smrg    close(fd);
183f29dbc25Smrg
184f29dbc25Smrg    if (!ret) {
18504007ebaSmrg        if (!memcmp(fix.id, "Geode", 5)) {
18604007ebaSmrg            *size = fix.smem_len;
18704007ebaSmrg            return 0;
18804007ebaSmrg        }
189f29dbc25Smrg    }
190f29dbc25Smrg
191f29dbc25Smrg    return -1;
192f29dbc25Smrg}
193f29dbc25Smrg
194f29dbc25Smrg#else
195f29dbc25Smrg
196f29dbc25Smrgint
197f29dbc25SmrgGeodeGetSizeFromFB(unsigned int *size)
198f29dbc25Smrg{
199f29dbc25Smrg    return -1;
200f29dbc25Smrg}
201f29dbc25Smrg
202f29dbc25Smrg#endif
203