1/*
2 * Copyright (c) 2007 Advanced Micro Devices, Inc.
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *
22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23 * contributors may be used to endorse or promote products derived from this
24 * software without specific prior written permission.
25 */
26
27/* We want to share as much code between GX and LX as we possibly can for obvious reasons */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <string.h>             /* memcmp() */
34#include <unistd.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include <sys/ioctl.h>
39
40#include "xorg-server.h"
41#include "xf86.h"
42#include "geode.h"
43
44#define move0(d,s,n) \
45  __asm__ __volatile__( \
46  "   rep; movsl\n" \
47  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
48  : "0" (n), "1" (s), "2" (d) \
49  : "memory")
50
51#define move1(d,s,n) \
52  __asm__ __volatile__( \
53  "   rep; movsl\n" \
54  "   movsb\n" \
55  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
56  : "0" (n), "1" (s), "2" (d) \
57  : "memory")
58
59#define move2(d,s,n) \
60  __asm__ __volatile__( \
61  "   rep; movsl\n" \
62  "   movsw\n" \
63  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
64  : "0" (n), "1" (s), "2" (d) \
65  : "memory")
66
67#define move3(d,s,n) \
68  __asm__ __volatile__( \
69  "   rep; movsl\n" \
70  "   movsw\n" \
71  "   movsb\n" \
72  : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
73  : "0" (n), "1" (s), "2" (d) \
74  : "memory")
75
76void
77geode_memory_to_screen_blt(unsigned long src, unsigned long dst,
78                           unsigned long sp, unsigned long dp, long w, long h,
79                           int bpp)
80{
81    int d0, d1, d2;
82    int n = w * (bpp >> 3);
83    int m = n >> 2;
84
85    switch (n & 3) {
86    case 0:
87        while (--h >= 0) {
88            move0(dst, src, m);
89            src += sp;
90            dst += dp;
91        }
92        break;
93    case 1:
94        while (--h >= 0) {
95            move1(dst, src, m);
96            src += sp;
97            dst += dp;
98        }
99        break;
100    case 2:
101        while (--h >= 0) {
102            move2(dst, src, m);
103            src += sp;
104            dst += dp;
105        }
106        break;
107    case 3:
108        while (--h >= 0) {
109            move3(dst, src, m);
110            src += sp;
111            dst += dp;
112        }
113        break;
114    }
115}
116
117/* I borrowed this function from the i830 driver - its much better
118   then what we had before
119*/
120
121int
122GeodeGetRefreshRate(DisplayModePtr pMode)
123{
124    if (pMode->VRefresh)
125        return (int) (pMode->VRefresh + 0.5);
126
127    return (int) (pMode->Clock * 1000.0 / pMode->HTotal / pMode->VTotal + 0.5);
128}
129
130/* This is used by both GX and LX.  It could be accelerated for LX, probably, but
131   that would involve a two pass blt, the first to copy the data, and the second
132   to copy the grey (using a pattern).  That seems like a bit of work for a
133   very underused format - so we'll just use the slow version.
134*/
135
136void
137GeodeCopyGreyscale(unsigned char *src, unsigned char *dst,
138                   int dstPitch, int srcPitch, int h, int w)
139{
140    int i;
141    unsigned char *src2 = src;
142    unsigned char *dst2 = dst;
143    unsigned char *dst3;
144    unsigned char *src3;
145
146    dstPitch <<= 1;
147
148    while (h--) {
149        dst3 = dst2;
150        src3 = src2;
151        for (i = 0; i < w; i++) {
152            *dst3++ = *src3++;  /* Copy Y data */
153            *dst3++ = 0x80;     /* Fill UV with 0x80 - greyscale */
154        }
155
156        src3 = src2;
157        for (i = 0; i < w; i++) {
158            *dst3++ = *src3++;  /* Copy Y data */
159            *dst3++ = 0x80;     /* Fill UV with 0x80 - greyscale */
160        }
161
162        dst2 += dstPitch;
163        src2 += srcPitch;
164    }
165}
166
167#if defined(linux)
168
169#include <linux/fb.h>
170
171int
172GeodeGetSizeFromFB(unsigned int *size)
173{
174    struct fb_fix_screeninfo fix;
175    int ret;
176    int fd = open("/dev/fb0", O_RDONLY);
177
178    if (fd == -1)
179        return -1;
180
181    ret = ioctl(fd, FBIOGET_FSCREENINFO, &fix);
182    close(fd);
183
184    if (!ret) {
185        if (!memcmp(fix.id, "Geode", 5)) {
186            *size = fix.smem_len;
187            return 0;
188        }
189    }
190
191    return -1;
192}
193
194#else
195
196int
197GeodeGetSizeFromFB(unsigned int *size)
198{
199    return -1;
200}
201
202#endif
203