]> git.proxmox.com Git - qemu.git/blobdiff - hw/omap_lcdc.c
ui: move files to ui/ and include/ui/
[qemu.git] / hw / omap_lcdc.c
index a27f244a9ebc2337dcdea7e427bab0f2bcc16a51..936850a6216ba6f3938d045795c168f4e8af45e1 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "hw.h"
-#include "console.h"
+#include "ui/console.h"
 #include "omap.h"
+#include "framebuffer.h"
+#include "ui/pixel_ops.h"
 
 struct omap_lcd_panel_s {
+    MemoryRegion *sysmem;
+    MemoryRegion iomem;
     qemu_irq irq;
     DisplayState *state;
-    QEMUConsole *console;
-    ram_addr_t imif_base;
-    ram_addr_t emiff_base;
 
     int plm;
     int tft;
@@ -68,10 +67,7 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
     qemu_irq_lower(s->irq);
 }
 
-#include "pixel_ops.h"
-
-typedef void draw_line_func(
-                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal);
+#define draw_line_func drawfn
 
 #define DEPTH 8
 #include "omap_lcd_template.h"
@@ -82,32 +78,32 @@ typedef void draw_line_func(
 #define DEPTH 32
 #include "omap_lcd_template.h"
 
-static draw_line_func *draw_line_table2[33] = {
-    [0 ... 32] = 0,
+static draw_line_func draw_line_table2[33] = {
+    [0 ... 32] = NULL,
     [8]                = draw_line2_8,
     [15]       = draw_line2_15,
     [16]       = draw_line2_16,
     [32]       = draw_line2_32,
-}, *draw_line_table4[33] = {
-    [0 ... 32] = 0,
+}, draw_line_table4[33] = {
+    [0 ... 32] = NULL,
     [8]                = draw_line4_8,
     [15]       = draw_line4_15,
     [16]       = draw_line4_16,
     [32]       = draw_line4_32,
-}, *draw_line_table8[33] = {
-    [0 ... 32] = 0,
+}, draw_line_table8[33] = {
+    [0 ... 32] = NULL,
     [8]                = draw_line8_8,
     [15]       = draw_line8_15,
     [16]       = draw_line8_16,
     [32]       = draw_line8_32,
-}, *draw_line_table12[33] = {
-    [0 ... 32] = 0,
+}, draw_line_table12[33] = {
+    [0 ... 32] = NULL,
     [8]                = draw_line12_8,
     [15]       = draw_line12_15,
     [16]       = draw_line12_16,
     [32]       = draw_line12_32,
-}, *draw_line_table16[33] = {
-    [0 ... 32] = 0,
+}, draw_line_table16[33] = {
+    [0 ... 32] = NULL,
     [8]                = draw_line16_8,
     [15]       = draw_line16_15,
     [16]       = draw_line16_16,
@@ -117,11 +113,10 @@ static draw_line_func *draw_line_table2[33] = {
 static void omap_update_display(void *opaque)
 {
     struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
-    draw_line_func *draw_line;
-    int size, dirty[2], minline, maxline, height;
-    int line, width, linesize, step, bpp, frame_offset;
-    ram_addr_t frame_base, scanline, newline, x;
-    uint8_t *s, *d;
+    draw_line_func draw_line;
+    int size, height, first, last;
+    int width, linesize, step, bpp, frame_offset;
+    hwaddr frame_base;
 
     if (!omap_lcd || omap_lcd->plm == 1 ||
                     !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state))
@@ -129,9 +124,9 @@ static void omap_update_display(void *opaque)
 
     frame_offset = 0;
     if (omap_lcd->plm != 2) {
-        memcpy(omap_lcd->palette, phys_ram_base +
-                        omap_lcd->dma->phys_framebuffer[
-                        omap_lcd->dma->current_frame], 0x200);
+        cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[
+                                  omap_lcd->dma->current_frame],
+                                 (void *)omap_lcd->palette, 0x200);
         switch (omap_lcd->palette[0] >> 12 & 7) {
         case 3 ... 7:
             frame_offset += 0x200;
@@ -175,7 +170,7 @@ static void omap_update_display(void *opaque)
     width = omap_lcd->width;
     if (width != ds_get_width(omap_lcd->state) ||
             omap_lcd->height != ds_get_height(omap_lcd->state)) {
-        qemu_console_resize(omap_lcd->console,
+        qemu_console_resize(omap_lcd->state,
                             omap_lcd->width, omap_lcd->height);
         omap_lcd->invalidate = 1;
     }
@@ -204,63 +199,48 @@ static void omap_update_display(void *opaque)
     if (!ds_get_bits_per_pixel(omap_lcd->state))
         return;
 
-    line = 0;
+    first = 0;
     height = omap_lcd->height;
     if (omap_lcd->subpanel & (1 << 31)) {
         if (omap_lcd->subpanel & (1 << 29))
-            line = (omap_lcd->subpanel >> 16) & 0x3ff;
+            first = (omap_lcd->subpanel >> 16) & 0x3ff;
         else
             height = (omap_lcd->subpanel >> 16) & 0x3ff;
         /* TODO: fill the rest of the panel with DPD */
     }
+
     step = width * bpp >> 3;
-    scanline = frame_base + step * line;
-    s = (uint8_t *) (phys_ram_base + scanline);
-    d = ds_get_data(omap_lcd->state);
     linesize = ds_get_linesize(omap_lcd->state);
-
-    dirty[0] = dirty[1] =
-            cpu_physical_memory_get_dirty(scanline, VGA_DIRTY_FLAG);
-    minline = height;
-    maxline = line;
-    for (; line < height; line ++) {
-        newline = scanline + step;
-        for (x = scanline + TARGET_PAGE_SIZE; x < newline;
-                        x += TARGET_PAGE_SIZE) {
-            dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG);
-            dirty[0] |= dirty[1];
-        }
-        if (dirty[0] || omap_lcd->invalidate) {
-            draw_line(d, s, width, omap_lcd->palette);
-            if (line < minline)
-                minline = line;
-            maxline = line + 1;
-        }
-        scanline = newline;
-        dirty[0] = dirty[1];
-        s += step;
-        d += linesize;
-    }
-
-    if (maxline >= minline) {
-        dpy_update(omap_lcd->state, 0, minline, width, maxline);
-        cpu_physical_memory_reset_dirty(frame_base + step * minline,
-                        frame_base + step * maxline, VGA_DIRTY_FLAG);
+    framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem,
+                               frame_base, width, height,
+                               step, linesize, 0,
+                               omap_lcd->invalidate,
+                               draw_line, omap_lcd->palette,
+                               &first, &last);
+    if (first >= 0) {
+        dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
     }
+    omap_lcd->invalidate = 0;
 }
 
-static int ppm_save(const char *filename, uint8_t *data,
-                int w, int h, int linesize)
+static void omap_ppm_save(const char *filename, uint8_t *data,
+                    int w, int h, int linesize, Error **errp)
 {
     FILE *f;
     uint8_t *d, *d1;
     unsigned int v;
-    int y, x, bpp;
+    int ret, y, x, bpp;
 
     f = fopen(filename, "wb");
-    if (!f)
-        return -1;
-    fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
+        return;
+    }
+    ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
+    if (ret < 0) {
+        goto write_err;
+    }
     d1 = data;
     bpp = linesize / w;
     for (y = 0; y < h; y ++) {
@@ -269,33 +249,61 @@ static int ppm_save(const char *filename, uint8_t *data,
             v = *(uint32_t *) d;
             switch (bpp) {
             case 2:
-                fputc((v >> 8) & 0xf8, f);
-                fputc((v >> 3) & 0xfc, f);
-                fputc((v << 3) & 0xf8, f);
+                ret = fputc((v >> 8) & 0xf8, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v >> 3) & 0xfc, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v << 3) & 0xf8, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
                 break;
             case 3:
             case 4:
             default:
-                fputc((v >> 16) & 0xff, f);
-                fputc((v >> 8) & 0xff, f);
-                fputc((v) & 0xff, f);
+                ret = fputc((v >> 16) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v >> 8) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
                 break;
             }
             d += bpp;
         }
         d1 += linesize;
     }
+out:
     fclose(f);
-    return 0;
+    return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
-static void omap_screen_dump(void *opaque, const char *filename) {
+static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
+                             Error **errp)
+{
     struct omap_lcd_panel_s *omap_lcd = opaque;
+
     omap_update_display(opaque);
     if (omap_lcd && ds_get_data(omap_lcd->state))
-        ppm_save(filename, ds_get_data(omap_lcd->state),
-                omap_lcd->width, omap_lcd->height,
-                ds_get_linesize(omap_lcd->state));
+        omap_ppm_save(filename, ds_get_data(omap_lcd->state),
+                    omap_lcd->width, omap_lcd->height,
+                    ds_get_linesize(omap_lcd->state), errp);
 }
 
 static void omap_invalidate_display(void *opaque) {
@@ -338,31 +346,20 @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) {
         return;
     }
 
-     if (s->dma->src == imif) {
-        /* Framebuffers are in SRAM */
-        s->dma->phys_framebuffer[0] = s->imif_base +
-                s->dma->src_f1_top - OMAP_IMIF_BASE;
-
-        s->dma->phys_framebuffer[1] = s->imif_base +
-                s->dma->src_f2_top - OMAP_IMIF_BASE;
-    } else {
-        /* Framebuffers are in RAM */
-        s->dma->phys_framebuffer[0] = s->emiff_base +
-                s->dma->src_f1_top - OMAP_EMIFF_BASE;
-
-        s->dma->phys_framebuffer[1] = s->emiff_base +
-                s->dma->src_f2_top - OMAP_EMIFF_BASE;
-    }
+    s->dma->phys_framebuffer[0] = s->dma->src_f1_top;
+    s->dma->phys_framebuffer[1] = s->dma->src_f2_top;
 
     if (s->plm != 2 && !s->palette_done) {
-        memcpy(s->palette, phys_ram_base +
-                s->dma->phys_framebuffer[s->dma->current_frame], 0x200);
+        cpu_physical_memory_read(
+            s->dma->phys_framebuffer[s->dma->current_frame],
+            (void *)s->palette, 0x200);
         s->palette_done = 1;
         omap_lcd_interrupts(s);
     }
 }
 
-static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
+                               unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -394,8 +391,8 @@ static uint32_t omap_lcdc_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+static void omap_lcdc_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
 {
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
 
@@ -438,16 +435,10 @@ static void omap_lcdc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc *omap_lcdc_readfn[] = {
-    omap_lcdc_read,
-    omap_lcdc_read,
-    omap_lcdc_read,
-};
-
-static CPUWriteMemoryFunc *omap_lcdc_writefn[] = {
-    omap_lcdc_write,
-    omap_lcdc_write,
-    omap_lcdc_write,
+static const MemoryRegionOps omap_lcdc_ops = {
+    .read = omap_lcdc_read,
+    .write = omap_lcdc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 void omap_lcdc_reset(struct omap_lcd_panel_s *s)
@@ -472,28 +463,26 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s)
     s->ctrl = 0;
 }
 
-struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                struct omap_dma_lcd_channel_s *dma, DisplayState *ds,
-                ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk)
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+                                        hwaddr base,
+                                        qemu_irq irq,
+                                        struct omap_dma_lcd_channel_s *dma,
+                                        omap_clk clk)
 {
-    int iomemtype;
     struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *)
-            qemu_mallocz(sizeof(struct omap_lcd_panel_s));
+            g_malloc0(sizeof(struct omap_lcd_panel_s));
 
     s->irq = irq;
     s->dma = dma;
-    s->state = ds;
-    s->imif_base = imif_base;
-    s->emiff_base = emiff_base;
+    s->sysmem = sysmem;
     omap_lcdc_reset(s);
 
-    iomemtype = cpu_register_io_memory(0, omap_lcdc_readfn,
-                    omap_lcdc_writefn, s);
-    cpu_register_physical_memory(base, 0x100, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->console = graphic_console_init(ds, omap_update_display,
-                                      omap_invalidate_display,
-                                      omap_screen_dump, NULL, s);
+    s->state = graphic_console_init(omap_update_display,
+                                    omap_invalidate_display,
+                                    omap_screen_dump, NULL, s);
 
     return s;
 }