Subversion Repositories Kolibri OS

Rev

Rev 3031 | Rev 5060 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *
  3.  * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
  4.  *
  5.  * All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sub license, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the
  16.  * next paragraph) shall be included in all copies or substantial portions
  17.  * of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  23.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  */
  28.  
  29. #include "dvo.h"
  30. #include "i915_reg.h"
  31. #include "i915_drv.h"
  32.  
  33. #define NS2501_VID 0x1305
  34. #define NS2501_DID 0x6726
  35.  
  36. #define NS2501_VID_LO 0x00
  37. #define NS2501_VID_HI 0x01
  38. #define NS2501_DID_LO 0x02
  39. #define NS2501_DID_HI 0x03
  40. #define NS2501_REV 0x04
  41. #define NS2501_RSVD 0x05
  42. #define NS2501_FREQ_LO 0x06
  43. #define NS2501_FREQ_HI 0x07
  44.  
  45. #define NS2501_REG8 0x08
  46. #define NS2501_8_VEN (1<<5)
  47. #define NS2501_8_HEN (1<<4)
  48. #define NS2501_8_DSEL (1<<3)
  49. #define NS2501_8_BPAS (1<<2)
  50. #define NS2501_8_RSVD (1<<1)
  51. #define NS2501_8_PD (1<<0)
  52.  
  53. #define NS2501_REG9 0x09
  54. #define NS2501_9_VLOW (1<<7)
  55. #define NS2501_9_MSEL_MASK (0x7<<4)
  56. #define NS2501_9_TSEL (1<<3)
  57. #define NS2501_9_RSEN (1<<2)
  58. #define NS2501_9_RSVD (1<<1)
  59. #define NS2501_9_MDI (1<<0)
  60.  
  61. #define NS2501_REGC 0x0c
  62.  
  63. struct ns2501_priv {
  64.         //I2CDevRec d;
  65.         bool quiet;
  66.         int reg_8_shadow;
  67.         int reg_8_set;
  68.         // Shadow registers for i915
  69.         int dvoc;
  70.         int pll_a;
  71.         int srcdim;
  72.         int fw_blc;
  73. };
  74.  
  75. #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
  76.  
  77. /*
  78.  * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
  79.  * laptops does not react on the i2c bus unless
  80.  * both the PLL is running and the display is configured in its native
  81.  * resolution.
  82.  * This function forces the DVO on, and stores the registers it touches.
  83.  * Afterwards, registers are restored to regular values.
  84.  *
  85.  * This is pretty much a hack, though it works.
  86.  * Without that, ns2501_readb and ns2501_writeb fail
  87.  * when switching the resolution.
  88.  */
  89.  
  90. /*
  91. ** Read a register from the ns2501.
  92. ** Returns true if successful, false otherwise.
  93. ** If it returns false, it might be wise to enable the
  94. ** DVO with the above function.
  95. */
  96. static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
  97. {
  98.         struct ns2501_priv *ns = dvo->dev_priv;
  99.         struct i2c_adapter *adapter = dvo->i2c_bus;
  100.         u8 out_buf[2];
  101.         u8 in_buf[2];
  102.  
  103.         struct i2c_msg msgs[] = {
  104.                 {
  105.                  .addr = dvo->slave_addr,
  106.                  .flags = 0,
  107.                  .len = 1,
  108.                  .buf = out_buf,
  109.                  },
  110.                 {
  111.                  .addr = dvo->slave_addr,
  112.                  .flags = I2C_M_RD,
  113.                  .len = 1,
  114.                  .buf = in_buf,
  115.                  }
  116.         };
  117.  
  118.         out_buf[0] = addr;
  119.         out_buf[1] = 0;
  120.  
  121.         if (i2c_transfer(adapter, msgs, 2) == 2) {
  122.                 *ch = in_buf[0];
  123.                 return true;
  124.         };
  125.  
  126.         if (!ns->quiet) {
  127.                 DRM_DEBUG_KMS
  128.                     ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
  129.                      adapter->name, dvo->slave_addr);
  130.         }
  131.  
  132.         return false;
  133. }
  134.  
  135. /*
  136. ** Write a register to the ns2501.
  137. ** Returns true if successful, false otherwise.
  138. ** If it returns false, it might be wise to enable the
  139. ** DVO with the above function.
  140. */
  141. static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
  142. {
  143.         struct ns2501_priv *ns = dvo->dev_priv;
  144.         struct i2c_adapter *adapter = dvo->i2c_bus;
  145.         uint8_t out_buf[2];
  146.  
  147.         struct i2c_msg msg = {
  148.                 .addr = dvo->slave_addr,
  149.                 .flags = 0,
  150.                 .len = 2,
  151.                 .buf = out_buf,
  152.         };
  153.  
  154.         out_buf[0] = addr;
  155.         out_buf[1] = ch;
  156.  
  157.         if (i2c_transfer(adapter, &msg, 1) == 1) {
  158.                 return true;
  159.         }
  160.  
  161.         if (!ns->quiet) {
  162.                 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
  163.                               addr, adapter->name, dvo->slave_addr);
  164.         }
  165.  
  166.         return false;
  167. }
  168.  
  169. /* National Semiconductor 2501 driver for chip on i2c bus
  170.  * scan for the chip on the bus.
  171.  * Hope the VBIOS initialized the PLL correctly so we can
  172.  * talk to it. If not, it will not be seen and not detected.
  173.  * Bummer!
  174.  */
  175. static bool ns2501_init(struct intel_dvo_device *dvo,
  176.                         struct i2c_adapter *adapter)
  177. {
  178.         /* this will detect the NS2501 chip on the specified i2c bus */
  179.         struct ns2501_priv *ns;
  180.         unsigned char ch;
  181.  
  182.         ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
  183.         if (ns == NULL)
  184.                 return false;
  185.  
  186.         dvo->i2c_bus = adapter;
  187.         dvo->dev_priv = ns;
  188.         ns->quiet = true;
  189.  
  190.         if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
  191.                 goto out;
  192.  
  193.         if (ch != (NS2501_VID & 0xff)) {
  194.                 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
  195.                               ch, adapter->name, dvo->slave_addr);
  196.                 goto out;
  197.         }
  198.  
  199.         if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
  200.                 goto out;
  201.  
  202.         if (ch != (NS2501_DID & 0xff)) {
  203.                 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
  204.                               ch, adapter->name, dvo->slave_addr);
  205.                 goto out;
  206.         }
  207.         ns->quiet = false;
  208.         ns->reg_8_set = 0;
  209.         ns->reg_8_shadow =
  210.             NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | NS2501_8_HEN;
  211.  
  212.         DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
  213.         return true;
  214.  
  215. out:
  216.         kfree(ns);
  217.         return false;
  218. }
  219.  
  220. static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
  221. {
  222.         /*
  223.          * This is a Laptop display, it doesn't have hotplugging.
  224.          * Even if not, the detection bit of the 2501 is unreliable as
  225.          * it only works for some display types.
  226.          * It is even more unreliable as the PLL must be active for
  227.          * allowing reading from the chiop.
  228.          */
  229.         return connector_status_connected;
  230. }
  231.  
  232. static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
  233.                                               struct drm_display_mode *mode)
  234. {
  235.         DRM_DEBUG_KMS
  236.             ("%s: is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
  237.              __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
  238.              mode->vtotal);
  239.  
  240.         /*
  241.          * Currently, these are all the modes I have data from.
  242.          * More might exist. Unclear how to find the native resolution
  243.          * of the panel in here so we could always accept it
  244.          * by disabling the scaler.
  245.          */
  246.         if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
  247.             (mode->hdisplay == 640 && mode->vdisplay == 480) ||
  248.             (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
  249.                 return MODE_OK;
  250.         } else {
  251.                 return MODE_ONE_SIZE;   /* Is this a reasonable error? */
  252.         }
  253. }
  254.  
  255. static void ns2501_mode_set(struct intel_dvo_device *dvo,
  256.                             struct drm_display_mode *mode,
  257.                             struct drm_display_mode *adjusted_mode)
  258. {
  259.         bool ok;
  260.         int retries = 10;
  261.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  262.  
  263.         DRM_DEBUG_KMS
  264.             ("%s: set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
  265.              __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
  266.              mode->vtotal);
  267.  
  268.         /*
  269.          * Where do I find the native resolution for which scaling is not required???
  270.          *
  271.          * First trigger the DVO on as otherwise the chip does not appear on the i2c
  272.          * bus.
  273.          */
  274.         do {
  275.                 ok = true;
  276.  
  277.                 if (mode->hdisplay == 800 && mode->vdisplay == 600) {
  278.                         /* mode 277 */
  279.                         ns->reg_8_shadow &= ~NS2501_8_BPAS;
  280.                         DRM_DEBUG_KMS("%s: switching to 800x600\n",
  281.                                       __FUNCTION__);
  282.  
  283.                         /*
  284.                          * No, I do not know where this data comes from.
  285.                          * It is just what the video bios left in the DVO, so
  286.                          * I'm just copying it here over.
  287.                          * This also means that I cannot support any other modes
  288.                          * except the ones supported by the bios.
  289.                          */
  290.                         ok &= ns2501_writeb(dvo, 0x11, 0xc8);   // 0xc7 also works.
  291.                         ok &= ns2501_writeb(dvo, 0x1b, 0x19);
  292.                         ok &= ns2501_writeb(dvo, 0x1c, 0x62);   // VBIOS left 0x64 here, but 0x62 works nicer
  293.                         ok &= ns2501_writeb(dvo, 0x1d, 0x02);
  294.  
  295.                         ok &= ns2501_writeb(dvo, 0x34, 0x03);
  296.                         ok &= ns2501_writeb(dvo, 0x35, 0xff);
  297.  
  298.                         ok &= ns2501_writeb(dvo, 0x80, 0x27);
  299.                         ok &= ns2501_writeb(dvo, 0x81, 0x03);
  300.                         ok &= ns2501_writeb(dvo, 0x82, 0x41);
  301.                         ok &= ns2501_writeb(dvo, 0x83, 0x05);
  302.  
  303.                         ok &= ns2501_writeb(dvo, 0x8d, 0x02);
  304.                         ok &= ns2501_writeb(dvo, 0x8e, 0x04);
  305.                         ok &= ns2501_writeb(dvo, 0x8f, 0x00);
  306.  
  307.                         ok &= ns2501_writeb(dvo, 0x90, 0xfe);   /* vertical. VBIOS left 0xff here, but 0xfe works better */
  308.                         ok &= ns2501_writeb(dvo, 0x91, 0x07);
  309.                         ok &= ns2501_writeb(dvo, 0x94, 0x00);
  310.                         ok &= ns2501_writeb(dvo, 0x95, 0x00);
  311.  
  312.                         ok &= ns2501_writeb(dvo, 0x96, 0x00);
  313.  
  314.                         ok &= ns2501_writeb(dvo, 0x99, 0x00);
  315.                         ok &= ns2501_writeb(dvo, 0x9a, 0x88);
  316.  
  317.                         ok &= ns2501_writeb(dvo, 0x9c, 0x23);   /* Looks like first and last line of the image. */
  318.                         ok &= ns2501_writeb(dvo, 0x9d, 0x00);
  319.                         ok &= ns2501_writeb(dvo, 0x9e, 0x25);
  320.                         ok &= ns2501_writeb(dvo, 0x9f, 0x03);
  321.  
  322.                         ok &= ns2501_writeb(dvo, 0xa4, 0x80);
  323.  
  324.                         ok &= ns2501_writeb(dvo, 0xb6, 0x00);
  325.  
  326.                         ok &= ns2501_writeb(dvo, 0xb9, 0xc8);   /* horizontal? */
  327.                         ok &= ns2501_writeb(dvo, 0xba, 0x00);   /* horizontal? */
  328.  
  329.                         ok &= ns2501_writeb(dvo, 0xc0, 0x05);   /* horizontal? */
  330.                         ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
  331.  
  332.                         ok &= ns2501_writeb(dvo, 0xc2, 0x00);
  333.                         ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
  334.  
  335.                         ok &= ns2501_writeb(dvo, 0xc4, 0x03);
  336.                         ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
  337.  
  338.                         ok &= ns2501_writeb(dvo, 0xc6, 0x00);
  339.                         ok &= ns2501_writeb(dvo, 0xc7, 0x73);
  340.                         ok &= ns2501_writeb(dvo, 0xc8, 0x02);
  341.  
  342.                 } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
  343.                         /* mode 274 */
  344.                         DRM_DEBUG_KMS("%s: switching to 640x480\n",
  345.                                       __FUNCTION__);
  346.                         /*
  347.                          * No, I do not know where this data comes from.
  348.                          * It is just what the video bios left in the DVO, so
  349.                          * I'm just copying it here over.
  350.                          * This also means that I cannot support any other modes
  351.                          * except the ones supported by the bios.
  352.                          */
  353.                         ns->reg_8_shadow &= ~NS2501_8_BPAS;
  354.  
  355.                         ok &= ns2501_writeb(dvo, 0x11, 0xa0);
  356.                         ok &= ns2501_writeb(dvo, 0x1b, 0x11);
  357.                         ok &= ns2501_writeb(dvo, 0x1c, 0x54);
  358.                         ok &= ns2501_writeb(dvo, 0x1d, 0x03);
  359.  
  360.                         ok &= ns2501_writeb(dvo, 0x34, 0x03);
  361.                         ok &= ns2501_writeb(dvo, 0x35, 0xff);
  362.  
  363.                         ok &= ns2501_writeb(dvo, 0x80, 0xff);
  364.                         ok &= ns2501_writeb(dvo, 0x81, 0x07);
  365.                         ok &= ns2501_writeb(dvo, 0x82, 0x3d);
  366.                         ok &= ns2501_writeb(dvo, 0x83, 0x05);
  367.  
  368.                         ok &= ns2501_writeb(dvo, 0x8d, 0x02);
  369.                         ok &= ns2501_writeb(dvo, 0x8e, 0x10);
  370.                         ok &= ns2501_writeb(dvo, 0x8f, 0x00);
  371.  
  372.                         ok &= ns2501_writeb(dvo, 0x90, 0xff);   /* vertical */
  373.                         ok &= ns2501_writeb(dvo, 0x91, 0x07);
  374.                         ok &= ns2501_writeb(dvo, 0x94, 0x00);
  375.                         ok &= ns2501_writeb(dvo, 0x95, 0x00);
  376.  
  377.                         ok &= ns2501_writeb(dvo, 0x96, 0x05);
  378.  
  379.                         ok &= ns2501_writeb(dvo, 0x99, 0x00);
  380.                         ok &= ns2501_writeb(dvo, 0x9a, 0x88);
  381.  
  382.                         ok &= ns2501_writeb(dvo, 0x9c, 0x24);
  383.                         ok &= ns2501_writeb(dvo, 0x9d, 0x00);
  384.                         ok &= ns2501_writeb(dvo, 0x9e, 0x25);
  385.                         ok &= ns2501_writeb(dvo, 0x9f, 0x03);
  386.  
  387.                         ok &= ns2501_writeb(dvo, 0xa4, 0x84);
  388.  
  389.                         ok &= ns2501_writeb(dvo, 0xb6, 0x09);
  390.  
  391.                         ok &= ns2501_writeb(dvo, 0xb9, 0xa0);   /* horizontal? */
  392.                         ok &= ns2501_writeb(dvo, 0xba, 0x00);   /* horizontal? */
  393.  
  394.                         ok &= ns2501_writeb(dvo, 0xc0, 0x05);   /* horizontal? */
  395.                         ok &= ns2501_writeb(dvo, 0xc1, 0x90);
  396.  
  397.                         ok &= ns2501_writeb(dvo, 0xc2, 0x00);
  398.                         ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
  399.  
  400.                         ok &= ns2501_writeb(dvo, 0xc4, 0x03);
  401.                         ok &= ns2501_writeb(dvo, 0xc5, 0x16);
  402.  
  403.                         ok &= ns2501_writeb(dvo, 0xc6, 0x00);
  404.                         ok &= ns2501_writeb(dvo, 0xc7, 0x02);
  405.                         ok &= ns2501_writeb(dvo, 0xc8, 0x02);
  406.  
  407.                 } else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
  408.                         /* mode 280 */
  409.                         DRM_DEBUG_KMS("%s: switching to 1024x768\n",
  410.                                       __FUNCTION__);
  411.                         /*
  412.                          * This might or might not work, actually. I'm silently
  413.                          * assuming here that the native panel resolution is
  414.                          * 1024x768. If not, then this leaves the scaler disabled
  415.                          * generating a picture that is likely not the expected.
  416.                          *
  417.                          * Problem is that I do not know where to take the panel
  418.                          * dimensions from.
  419.                          *
  420.                          * Enable the bypass, scaling not required.
  421.                          *
  422.                          * The scaler registers are irrelevant here....
  423.                          *
  424.                          */
  425.                         ns->reg_8_shadow |= NS2501_8_BPAS;
  426.                         ok &= ns2501_writeb(dvo, 0x37, 0x44);
  427.                 } else {
  428.                         /*
  429.                          * Data not known. Bummer!
  430.                          * Hopefully, the code should not go here
  431.                          * as mode_OK delivered no other modes.
  432.                          */
  433.                         ns->reg_8_shadow |= NS2501_8_BPAS;
  434.                 }
  435.                 ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
  436.         } while (!ok && retries--);
  437. }
  438.  
  439. /* set the NS2501 power state */
  440. static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
  441. {
  442.         unsigned char ch;
  443.  
  444.         if (!ns2501_readb(dvo, NS2501_REG8, &ch))
  445.                 return false;
  446.  
  447.         if (ch & NS2501_8_PD)
  448.                 return true;
  449.         else
  450.                 return false;
  451. }
  452.  
  453. /* set the NS2501 power state */
  454. static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
  455. {
  456.         bool ok;
  457.         int retries = 10;
  458.         struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
  459.         unsigned char ch;
  460.  
  461.         DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to %i\n",
  462.                       __FUNCTION__, enable);
  463.  
  464.         ch = ns->reg_8_shadow;
  465.  
  466.         if (enable)
  467.                 ch |= NS2501_8_PD;
  468.         else
  469.                 ch &= ~NS2501_8_PD;
  470.  
  471.         if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
  472.                 ns->reg_8_set = 1;
  473.                 ns->reg_8_shadow = ch;
  474.  
  475.                 do {
  476.                         ok = true;
  477.                         ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
  478.                         ok &=
  479.                             ns2501_writeb(dvo, 0x34,
  480.                                           enable ? 0x03 : 0x00);
  481.                         ok &=
  482.                             ns2501_writeb(dvo, 0x35,
  483.                                           enable ? 0xff : 0x00);
  484.                 } while (!ok && retries--);
  485.         }
  486. }
  487.  
  488. static void ns2501_dump_regs(struct intel_dvo_device *dvo)
  489. {
  490.         uint8_t val;
  491.  
  492.         ns2501_readb(dvo, NS2501_FREQ_LO, &val);
  493.         DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
  494.         ns2501_readb(dvo, NS2501_FREQ_HI, &val);
  495.         DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
  496.         ns2501_readb(dvo, NS2501_REG8, &val);
  497.         DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
  498.         ns2501_readb(dvo, NS2501_REG9, &val);
  499.         DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
  500.         ns2501_readb(dvo, NS2501_REGC, &val);
  501.         DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
  502. }
  503.  
  504. static void ns2501_destroy(struct intel_dvo_device *dvo)
  505. {
  506.         struct ns2501_priv *ns = dvo->dev_priv;
  507.  
  508.         if (ns) {
  509.                 kfree(ns);
  510.                 dvo->dev_priv = NULL;
  511.         }
  512. }
  513.  
  514. struct intel_dvo_dev_ops ns2501_ops = {
  515.         .init = ns2501_init,
  516.         .detect = ns2501_detect,
  517.         .mode_valid = ns2501_mode_valid,
  518.         .mode_set = ns2501_mode_set,
  519.         .dpms = ns2501_dpms,
  520.         .get_hw_state = ns2501_get_hw_state,
  521.         .dump_regs = ns2501_dump_regs,
  522.         .destroy = ns2501_destroy,
  523. };
  524.