[PATCH 16/28] [OMAPZOOM] OMAP: CAM: Add MMS Kernel changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Sergio Aguirre <saaguirre@xxxxxx>

OMAP: CAM: Add MMS Kernel changes

This adds MMS changes to the OMAP34xx camera driver. Including:
- HQ capture

NOTE: Credits to MMS crew for all this.

Signed-off-by: Sergio Aguirre <saaguirre@xxxxxx>
---
 drivers/media/video/isp/isp.c        |   40 ++++++++---
 drivers/media/video/isp/isp_af.c     |   28 +++++---
 drivers/media/video/isp/ispccdc.c    |  117 ++++++++++++++++++++++++++++++++---
 drivers/media/video/isp/ispccdc.h    |    4 -
 drivers/media/video/isp/isph3a.c     |   12 +++
 drivers/media/video/isp/ispmmu.h     |    2
 drivers/media/video/isp/isppreview.c |    3
 drivers/media/video/isp/isppreview.h |    9 ++
 8 files changed, 180 insertions(+), 35 deletions(-)

Index: omapkernel/drivers/media/video/isp/isp.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isp.c       2008-10-15 19:37:26.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isp.c    2008-10-15 19:40:02.000000000 -0500
@@ -71,6 +71,10 @@
                .description = "Bayer10 (GrR/BGb)",
                .pixelformat = V4L2_PIX_FMT_SGRBG10,
        },
+       {
+               .description = "Bayer10 (pattern)",
+               .pixelformat = V4L2_PIX_FMT_PATT,
+       }
 };

 /* ISP Crop capabilities */
@@ -980,6 +984,14 @@
                goto out;
        }

+       if ((irqstatus & HS_VS) == HS_VS) {
+               if (irqdis->isp_callbk[CBK_HS_VS])
+                       irqdis->isp_callbk[CBK_HS_VS](HS_VS,
+                               irqdis->isp_callbk_arg1[CBK_HS_VS],
+                               irqdis->isp_callbk_arg2[CBK_HS_VS]);
+               is_irqhandled = 1;
+       }
+
        if ((irqstatus & CCDC_VD1) == CCDC_VD1) {
                if (irqdis->isp_callbk[CBK_CCDC_VD1])
                                irqdis->isp_callbk[CBK_CCDC_VD1](CCDC_VD1,
@@ -1028,14 +1040,6 @@
                is_irqhandled = 1;
        }

-       if ((irqstatus & HS_VS) == HS_VS) {
-               if (irqdis->isp_callbk[CBK_HS_VS])
-                       irqdis->isp_callbk[CBK_HS_VS](HS_VS,
-                               irqdis->isp_callbk_arg1[CBK_HS_VS],
-                               irqdis->isp_callbk_arg2[CBK_HS_VS]);
-               is_irqhandled = 1;
-       }
-
        if ((irqstatus & H3A_AF_DONE) == H3A_AF_DONE) {
                if (irqdis->isp_callbk[CBK_H3A_AF_DONE])
                        irqdis->isp_callbk[CBK_H3A_AF_DONE](H3A_AF_DONE,
@@ -1191,6 +1195,9 @@
                                                is_isppreview_enabled())
                isppreview_enable(1);

+       /* clear any pending IRQs */
+       omap_writel(0xFFFFFFFF, ISP_IRQ0STATUS);
+
        return;
 }
 EXPORT_SYMBOL(isp_start);
@@ -1258,7 +1265,8 @@

        isp_release_resources();
        if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10) &&
-               (pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10)) {
+               ((pix_output->pixelformat == V4L2_PIX_FMT_YUYV) ||
+               (pix_output->pixelformat == V4L2_PIX_FMT_UYVY))) {
                        ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC |
                                        OMAP_ISP_PREVIEW | OMAP_ISP_RESIZER;
                        ispccdc_request();
@@ -1277,15 +1285,23 @@
                isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_RSZ);
                ispresizer_config_datapath(RSZ_OTFLY_YUV);
 #endif
-       } else {
+       } else if (pix_input->pixelformat == pix_output->pixelformat) {
                ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC;
                ispccdc_request();
                if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10)
                        ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_MEM);
-               else
+               else if (pix_input->pixelformat == V4L2_PIX_FMT_PATT) {
+                       /* MMS */
+                       ispccdc_config_datapath(CCDC_RAW_PATTERN,
+                                                       CCDC_OTHERS_LSC_MEM);
+               } else if ((pix_input->pixelformat == V4L2_PIX_FMT_YUYV) ||
+                               (pix_input->pixelformat == V4L2_PIX_FMT_UYVY)) {
                        ispccdc_config_datapath(CCDC_YUV_SYNC,
                                                        CCDC_OTHERS_MEM);
-       }
+               } else
+                       return -EINVAL;
+       } else
+               return -EINVAL;
        return 0;
 }

Index: omapkernel/drivers/media/video/isp/isp_af.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isp_af.c    2008-10-15 19:37:24.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isp_af.c 2008-10-15 19:40:49.000000000 -0500
@@ -313,9 +313,10 @@
        busyaf = omap_readl(ISPH3A_PCR);

        if ((busyaf & AF_BUSYAF) == AF_BUSYAF) {
-               DPRINTK_ISPH3A("AF_register_setup_ERROR : Engine Busy");
-               DPRINTK_ISPH3A("\n Configuration cannot be done ");
-               return -AF_ERR_ENGINE_BUSY;
+               /* DPRINTK_ISPH3A("AF_register_setup_ERROR : Engine Busy"); */
+               /* DPRINTK_ISPH3A("\n Configuration cannot be done "); */
+               /* return -AF_ERR_ENGINE_BUSY; */
+               isp_af_enable(0);
        }

        /*Check IIR Coefficient and start Values */
@@ -396,8 +397,6 @@
        /*Set configuration flag to indicate HW setup done */
        if (af_dev_configptr->config->af_config)
                isp_af_enable(1);
-       else
-               isp_af_enable(0);

        /*Success */
        return 0;
@@ -702,9 +701,8 @@
 /* Function to Enable/Disable AF Engine */
 int isp_af_enable(int enable)
 {
-       unsigned int pcr;
-
-       pcr = omap_readl(ISPH3A_PCR);
+       /* Before enabling AF H3A we need to clear pending interrupts */
+       omap_writel(IRQ0STATUS_H3A_AF_DONE_IRQ, ISP_IRQ0STATUS);

        /* Set AF_EN bit in PCR Register */
        if (enable) {
@@ -714,12 +712,20 @@
                        return -EINVAL;
                }

-               pcr |= AF_EN;
+               omap_writel((omap_readl(ISPH3A_PCR) | AF_EN), ISPH3A_PCR);
        } else {
+               u32 timeout = 20;
                isp_unset_callback(CBK_H3A_AF_DONE);
-               pcr &= ~AF_EN;
+               omap_writel((omap_readl(ISPH3A_PCR) & ~AF_EN), ISPH3A_PCR);
+               while ((omap_readl(ISPH3A_PCR) & AF_BUSYAF) && timeout) {
+                       mdelay(10);
+                       timeout--;
+               }
+               if (timeout == 0) {
+                       printk(KERN_DEBUG "%s - can't disable AF H3A\n",
+                                                               __func__);
+               }
        }
-       omap_writel(pcr, ISPH3A_PCR);
        return 0;
 }

Index: omapkernel/drivers/media/video/isp/ispccdc.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/ispccdc.c   2008-10-15 19:37:25.000000000 -0500
+++ omapkernel/drivers/media/video/isp/ispccdc.c        2008-10-15 19:42:28.000000000 -0500
@@ -189,6 +189,11 @@
        } else {
                if ((ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) ==
                                        ISP_ABS_CCDC_BLCLAMP) {
+                       if (copy_from_user(&bclamp_t,
+                               (struct ispccdc_bclamp *)(ccdc_struct->bclamp),
+                               sizeof(struct ispccdc_bclamp)))
+                               goto copy_from_user_err;
+
                        ispccdc_enable_black_clamp(0);
                        ispccdc_config_black_clamp(bclamp_t);
                }
@@ -571,6 +576,19 @@
                ispccdc_config_vp(vpcfg);
                ispccdc_enable_vp(1);
                break;
+       case CCDC_OTHERS_LSC_MEM: /* Added by MMS */
+               syn_mode |= ISPCCDC_SYN_MODE_VP2SDR;
+               syn_mode |= ISPCCDC_SYN_MODE_WEN;
+               /* Generally cam_wen is used with cam_hs, vs signals */
+               syn_mode |= ISPCCDC_SYN_MODE_EXWEN;
+               omap_writel((omap_readl(ISPCCDC_CFG))
+                       | ISPCCDC_CFG_WENLOG, ISPCCDC_CFG);
+               /* Video Port Configuration */
+               vpcfg.bitshift_sel = BIT9_0;
+               vpcfg.freq_sel = PIXCLKBY2;
+               ispccdc_config_vp(vpcfg);
+               ispccdc_enable_vp(1);
+               break;
        default:
                DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output");
                return -EINVAL;
@@ -616,6 +634,32 @@
                blkcfg.dcsubval = 0;
                ispccdc_config_black_clamp(blkcfg);
                break;
+       /* Added by MMS */
+       case CCDC_RAW_PATTERN:
+               /* Slave mode */
+               syncif.ccdc_mastermode = 0;
+               /* Normal */
+               syncif.datapol = 0;
+               syncif.datsz = DAT8;
+               /* Progressive Mode */
+               syncif.fldmode = 0;
+               /* Input */
+               syncif.fldout = 0;
+               /* Positive */
+               syncif.fldpol = 0;
+               /* Odd Field */
+               syncif.fldstat = 0;
+               /* Positive */
+               syncif.hdpol = 0;
+               syncif.ipmod = RAW;
+               /* Positive */
+               syncif.vdpol = 0;
+               ispccdc_config_sync_if(syncif);
+               ispccdc_config_imgattr(colptn);
+               /* Config DC sub */
+               blkcfg.dcsubval = 42;
+               ispccdc_config_black_clamp(blkcfg);
+               break;
        case CCDC_YUV_BT:
                break;
        case CCDC_OTHERS:
@@ -644,6 +688,7 @@
        u32 syn_mode = omap_readl(ISPCCDC_SYN_MODE);

        syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
+       syn_mode &= ~ISPCCDC_SYN_MODE_PACK8; /* Added by MMS */

        if (syncif.fldstat)
                syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
@@ -668,6 +713,7 @@
        switch (syncif.datsz) {
        case DAT8:
                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
+               syn_mode |= ISPCCDC_SYN_MODE_PACK8; /* Added by MMS */
                break;
        case DAT10:
                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
@@ -837,10 +883,11 @@
 {
        u32 blcomp_val = 0;

-       blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
-       blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
-       blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
-       blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
+       blcomp_val |= (((u32)blcomp.b_mg & 0xFF) << ISPCCDC_BLKCMP_B_MG_SHIFT);
+       blcomp_val |= (((u32)blcomp.gb_g & 0xFF) << ISPCCDC_BLKCMP_GB_G_SHIFT);
+       blcomp_val |= (((u32)blcomp.gr_cy & 0xFF) <<
+                                               ISPCCDC_BLKCMP_GR_CY_SHIFT);
+       blcomp_val |= (((u32)blcomp.r_ye & 0xFF) << ISPCCDC_BLKCMP_R_YE_SHIFT);

        omap_writel(blcomp_val, ISPCCDC_BLKCMP);
 }
@@ -1087,7 +1134,9 @@

        if ((ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) ||
                                                (ispccdc_obj.ccdc_outfmt ==
-                                               CCDC_OTHERS_VP_MEM)) {
+                                               CCDC_OTHERS_VP_MEM) ||
+                                               (ispccdc_obj.ccdc_outfmt ==
+                                               CCDC_OTHERS_LSC_MEM)) {
                if (*output_w % 16) {
                        *output_w -= (*output_w % 16);
                        *output_w += 16;
@@ -1197,10 +1246,17 @@
                                        (ispccdc_obj.ccdcout_h <<
                                        ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
                                        ISPCCDC_VP_OUT);
+/* MMS: fix wrong pattern */
+/*
                omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
                                        ((ispccdc_obj.ccdcout_w - 1) <<
                                        ISPCCDC_HORZ_INFO_NPH_SHIFT),
                                        ISPCCDC_HORZ_INFO);
+*/
+               omap_writel(1 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+                                       ((ispccdc_obj.ccdcout_w - 1) <<
+                                       ISPCCDC_HORZ_INFO_NPH_SHIFT),
+                                       ISPCCDC_HORZ_INFO);
                omap_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
                                        ISPCCDC_VERT_START);
                omap_writel((ispccdc_obj.ccdcout_h - 1) <<
@@ -1212,10 +1268,47 @@
                                        ISPCCDC_VDINT_0_SHIFT) |
                                        ((50 & ISPCCDC_VDINT_1_MASK) <<
                                        ISPCCDC_VDINT_1_SHIFT), ISPCCDC_VDINT);
+       } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_LSC_MEM) {
+               /* Added by MMS */
+               /* Start with 1 pixel apart */
+               omap_writel((1 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT)
+                               | (ispccdc_obj.ccdcin_w
+                               << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
+                               ISPCCDC_FMT_HORZ);
+
+               omap_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT)
+                               | ((ispccdc_obj.ccdcin_h)
+                               << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
+                               ISPCCDC_FMT_VERT);
+
+               omap_writel((ispccdc_obj.ccdcout_w
+                               << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT)
+                               | (ispccdc_obj.ccdcout_h
+                               << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
+                               ISPCCDC_VP_OUT);
+               omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
+                               | ((ispccdc_obj.ccdcout_w - 1)
+                               << ISPCCDC_HORZ_INFO_NPH_SHIFT),
+                               ISPCCDC_HORZ_INFO);
+               omap_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
+                               ISPCCDC_VERT_START);
+               omap_writel((ispccdc_obj.ccdcout_h - 1)
+                               << ISPCCDC_VERT_LINES_NLV_SHIFT,
+                               ISPCCDC_VERT_LINES);
+               /*Configure the HSIZE_OFF with output buffer width*/
+
+               ispccdc_config_outlineoffset((ispccdc_obj.ccdcout_w * 2), 0, 0);
+               omap_writel((((ispccdc_obj.ccdcout_h - 25)
+                               & ISPCCDC_VDINT_0_MASK)
+                               << ISPCCDC_VDINT_0_SHIFT)
+                               | (((50) &  ISPCCDC_VDINT_1_MASK)
+                               << ISPCCDC_VDINT_1_SHIFT),
+                               ISPCCDC_VDINT);
        }

        if (is_isplsc_activated()) {
-               if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
+               if ((ispccdc_obj.ccdc_inpfmt == CCDC_RAW) ||
+                       (ispccdc_obj.ccdc_inpfmt == CCDC_RAW_PATTERN)) {
                        ispccdc_config_lsc(&lsc_config);
                        ispccdc_load_lsc(lsc_config.size);
                }
@@ -1318,9 +1411,10 @@
 {
        if (enable) {
                if (ccdc_use_lsc && !ispccdc_obj.lsc_en &&
-                       (ispccdc_obj.ccdc_inpfmt == CCDC_RAW))
+                       ((ispccdc_obj.ccdc_inpfmt == CCDC_RAW) ||
+                       (ispccdc_obj.ccdc_inpfmt == CCDC_RAW_PATTERN)))
                        ispccdc_enable_lsc(1);
-
+                       mdelay(10);
                        omap_writel(omap_readl(ISPCCDC_PCR) | (ISPCCDC_PCR_EN),
                                                                ISPCCDC_PCR);
        } else {
@@ -1442,6 +1536,13 @@
                                        omap_readl(ISPCCDC_LSC_TABLE_BASE));
        DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
                                        omap_readl(ISPCCDC_LSC_TABLE_OFFSET));
+       /* Added by MMS */
+       DPRINTK_ISPCCDC("###CCDC ISPCCDC_BLKCMP=0x%x\n",
+                                               omap_readl(ISPCCDC_BLKCMP));
+       DPRINTK_ISPCCDC("###CCDC ISPCCDC_DCSUB=0x%x\n",
+                                               omap_readl(ISPCCDC_DCSUB));
+       DPRINTK_ISPCCDC("###CCDC ISPCCDC_FPC=0x%x\n", omap_readl(ISPCCDC_FPC));
+
 }
 EXPORT_SYMBOL(ispccdc_print_status);

Index: omapkernel/drivers/media/video/isp/ispccdc.h
===================================================================
--- omapkernel.orig/drivers/media/video/isp/ispccdc.h   2008-10-15 19:25:00.000000000 -0500
+++ omapkernel/drivers/media/video/isp/ispccdc.h        2008-10-15 19:39:20.000000000 -0500
@@ -42,6 +42,7 @@
        CCDC_RAW,
        CCDC_YUV_SYNC,
        CCDC_YUV_BT,
+       CCDC_RAW_PATTERN,
        CCDC_OTHERS
 };

@@ -50,7 +51,8 @@
        CCDC_YUV_MEM_RSZ,
        CCDC_OTHERS_VP,
        CCDC_OTHERS_MEM,
-       CCDC_OTHERS_VP_MEM
+       CCDC_OTHERS_VP_MEM,
+       CCDC_OTHERS_LSC_MEM
 };

 /* Enumeration constants for the sync interface parameters */
Index: omapkernel/drivers/media/video/isp/isph3a.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isph3a.c    2008-10-15 19:37:24.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isph3a.c 2008-10-15 19:43:30.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <asm/cacheflush.h>
+#include <linux/delay.h>

 #include "isp.h"
 #include "ispreg.h"
@@ -215,9 +216,20 @@
                                                                ISPH3A_PCR);
                DPRINTK_ISPH3A("    H3A enabled \n");
        } else {
+               int timeout = 20;
                aewb_regs.reg_pcr &= ~ISPH3A_PCR_AEW_EN;
                omap_writel(omap_readl(ISPH3A_PCR) & ~ISPH3A_PCR_AEW_EN,
                                                                ISPH3A_PCR);
+               while ((omap_readl(ISPH3A_PCR) & ISPH3A_PCR_AEW_BUSY) &&
+                                                               timeout) {
+                       mdelay(10);
+                       timeout--;
+               }
+               if (timeout == 0) {
+                       printk(KERN_DEBUG "%s - can't disable AEWB H3A\n",
+                                                               __func__);
+               }
+
                DPRINTK_ISPH3A("    H3A disabled \n");
        }
        aewb_config_local.aewb_enable = enable;
Index: omapkernel/drivers/media/video/isp/ispmmu.h
===================================================================
--- omapkernel.orig/drivers/media/video/isp/ispmmu.h    2008-10-15 19:25:00.000000000 -0500
+++ omapkernel/drivers/media/video/isp/ispmmu.h 2008-10-15 19:39:20.000000000 -0500
@@ -65,7 +65,7 @@
  * to keep track of these 16 L2 page table's status.
  */
 #define L2P_TABLE_SIZE                 1024
-#define L2P_TABLE_NR                   41 /* Currently supports 4*5MP shots */
+#define L2P_TABLE_NR                   62 /* Currently supports 4*5MP shots */
 #define L2P_TABLES_SIZE                (L2P_TABLE_SIZE * L2P_TABLE_NR)

 /* Extra memory allocated to get ttb aligned on 16KB */
Index: omapkernel/drivers/media/video/isp/isppreview.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isppreview.c        2008-10-15 19:37:25.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isppreview.c     2008-10-15 19:44:09.000000000 -0500
@@ -69,7 +69,8 @@
        {ISPPRV_CDC_THR1, 0x0000},
        {ISPPRV_CDC_THR2, 0x0000},
        {ISPPRV_CDC_THR3, 0x0000},
-       {ISPPRV_PCR, 0x0000},
+/* Removed by MMS */
+/*     {ISPPRV_PCR, 0x0000}, */
        {ISP_TOK_TERM, 0x0000}
 };

Index: omapkernel/drivers/media/video/isp/isppreview.h
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isppreview.h        2008-10-15 19:37:24.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isppreview.h     2008-10-15 19:44:50.000000000 -0500
@@ -28,13 +28,20 @@
 #define ISPPRV_BRIGHT_DEF              0x1
 #define ISPPRV_BRIGHT_LOW              0x0
 #define ISPPRV_BRIGHT_HIGH             0xF
-#define ISPPRV_BRIGHT_UNITS            0x7
+#define ISPPRV_BRIGHT_UNITS            0x1

+/*
 #define ISPPRV_CONTRAST_STEP           0x1
 #define ISPPRV_CONTRAST_DEF            0x2
 #define ISPPRV_CONTRAST_LOW            0x0
 #define ISPPRV_CONTRAST_HIGH           0xF
 #define ISPPRV_CONTRAST_UNITS          0x5
+*/
+#define ISPPRV_CONTRAST_STEP           0x1
+#define ISPPRV_CONTRAST_DEF            0x1 /* MMS */
+#define ISPPRV_CONTRAST_LOW            0x0
+#define ISPPRV_CONTRAST_HIGH           0xF
+#define ISPPRV_CONTRAST_UNITS          0x16 /* MMS */

 #define NO_AVE                         0x0
 #define AVE_2_PIX                      0x1
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux